#include "all.h"

#if 0
		TITLE	FIXUPP2 - Copyright (c) SLR Systems 1994

		INCLUDE MACROS
		INCLUDE	SYMBOLS
		INCLUDE	SEGMENTS
		INCLUDE	GROUPS
		INCLUDE SECTS
		INCLUDE	SEGMSYMS
		INCLUDE	SECTIONS
		INCLUDE	EXES
		INCLUDE	FIXTEMPS
if	fg_segm
		INCLUDE RELOCSS
endif
if	fg_pe
		INCLUDE	PE_STRUC
endif
		INCLUDE	RELEASE

		PUBLIC	FIXUPP2,REL_CHK_LIDATA,FIX2_TARG_TABLE_CV,FIX2_TARG_TABLE_NORMAL,LOC_10_PROT,SPECIAL_RELOC_CHECK
		PUBLIC	DO_FARCALL_FIXUPPS,SELECT_CV4_OUTPUT


		.DATA

		EXTERNDEF	TEMP_DATA_RECORD:BYTE,TEMP_FIXUPP_RECORD:BYTE,LOC_SIZE:BYTE,EXETYPE_FLAG:BYTE,FIX2_TTYPE:BYTE
		EXTERNDEF	FIX2_FTYPE:BYTE,FIX2_SEG_TYPE:BYTE,FIX2_SM_FLAGS_2:BYTE,FIX2_LD_TYPE:BYTE,FIX2_FH_TYPE:BYTE

		EXTERNDEF	FIX2_LD_LENGTH:WORD,FIX2_FH_LENGTH:WORD

		EXTERNDEF	EXETABLE:DWORD,HEADER_TABLE:DWORD,VECTOR_SIZE:DWORD,MOVABLE_MASK:DWORD,LOC_10:DWORD
		EXTERNDEF	CURN_OUTFILE_GINDEX:DWORD,FIX2_TT:DWORD,SYMC_START:DWORD,LOC_CALLTBL_PTR:DWORD,SEGMENT_COUNT:DWORD
		EXTERNDEF	LDATA_SEGMOD_GINDEX:DWORD,CURNMOD_GINDEX:DWORD,CURN_SECTION_GINDEX:DWORD,LATEST_PENT_GINDEX:DWORD
		EXTERNDEF	MODEND_OWNER_GINDEX:DWORD,FIX2_LDATA_SEGMENT_GINDEX:DWORD,FIX2_FIXUPP_BLK:DWORD,GROUP_PTRS:DWORD
		EXTERNDEF	FIX2_FIXUPP_BASE:DWORD,FIX2_FIXUPP_EOR:DWORD,FIX2_FF:DWORD,FIX2_OS2_TNUMBER:DWORD
		EXTERNDEF	FIX2_OS2_FNUMBER:DWORD,FIX2_OS2_TFLAGS:DWORD,FIX2_OS2_FFLAGS:DWORD,FIX2_SEG_OS2_NUMBER:DWORD
		EXTERNDEF	FIX2_LDATA_BASE:DWORD,FIX2_FC_LENGTH:DWORD,FIX2_FC_SEGMOD_GINDEX:DWORD,FIRST_RELOC_GINDEX:DWORD
		EXTERNDEF	FIX2_SM_START:DWORD,FIX2_IMP_FLAGS:DWORD,FIX2_IMP_OFFSET:DWORD,FIX2_FH_BLOCK_BASE:DWORD
		EXTERNDEF	FIX2_IMP_MODULE:DWORD,FIX2_TFRAME_SEG:DWORD,FIX2_OFFSET:DWORD,FIX2_LOC:DWORD,FIX2_TINDEX:DWORD
		EXTERNDEF	FIX2_FINDEX:DWORD,FIX2_TARG_TABLE:DWORD,FIX2_FC_BLOCK_BASE:DWORD,ENTRYPOINT_GINDEX:DWORD
		EXTERNDEF	FIX2_LDATA_EOR:DWORD,FIX2_SM_NEXT_SEGMOD_GINDEX:DWORD,FIX2_SEG_GINDEX:DWORD
		EXTERNDEF	FIX2_SEG_OS2_FLAGS:DWORD,FIX2_NEW_SEGMOD_GINDEX:DWORD,FLAG_0C:DWORD,FIX2_RELOC_OFFSET:DWORD
		EXTERNDEF	RELOC_HIGH_WATER:DWORD,RELOC_BITS:DWORD,VECTOR_TABLE_ADDRESS:DWORD,SLR_CODE_HEADER:DWORD
		EXTERNDEF	FIRST_FARCALL:DWORD,END_VECTOR_TABLE:DWORD,WM_START_ADDR:DWORD,MODEND_ADDRESS:DWORD
		EXTERNDEF	SEGMENT_TABLE_PTR:DWORD,FIXUPP_COUNT:DWORD,FIX2_LDATA_PTR:DWORD,FIX2_TOFFSET:DWORD,FIX2_FFRAME:DWORD
		EXTERNDEF	FIX2_TFRAME:DWORD,FIX2_SM_FIRST_DAT:DWORD,FIX2_SM_LAST_DAT:DWORD,FIX2_FH_NEXT_FIXUPP:DWORD
		EXTERNDEF	FIX2_LDATA_LOC:DWORD,FIX2_SEG_FRAME:DWORD,FIX2_LD_NEXT_LDATA:DWORD,FIX2_LD_OFFSET:DWORD
		EXTERNDEF	FIX2_STACK_DELTA:DWORD,PE_BASE:DWORD,FIRST_SECTION_GINDEX:DWORD,FIX2_LD_BLOCK_BASE:DWORD

		EXTERNDEF	START_DEFINED_SEM:QWORD,SECTION_GARRAY:STD_PTR_S,SEGMOD_GARRAY:STD_PTR_S,PENT_GARRAY:STD_PTR_S
		EXTERNDEF	SEGMENT_GARRAY:STD_PTR_S,FIX2_FIXUPP_STUFF:FIXUPP_HEADER_TYPE,PEXEHEADER:PEXE
		EXTERNDEF	FIX2_SEGMENT_STUFF:SEGMENT_STRUCT,SYMBOL_GARRAY:STD_PTR_S,GROUP_GARRAY:STD_PTR_S
		EXTERNDEF	FIX2_SEGMOD_STUFF:SEGMOD_STRUCT,FIX2_LDATA_STUFF:LDATA_HEADER_TYPE,RELOC_GARRAY:STD_PTR_S
		EXTERNDEF	PE_OBJECT_GARRAY:STD_PTR_S,EXEHEADER:EXE,NEXEHEADER:NEXE,SEGMENT_TABLE:SEGTBL_STRUCT

		EXTERNDEF	OUT_SEGMOD_FINISH:DWORD,OUT_NEW_SEGMOD:DWORD,OUT_END_OF_SECTION:DWORD,OUT_END_OF_SEGMENTS:DWORD
		EXTERNDEF	OUT_NEW_SECTION:DWORD,OUT_NEW_SEGMENT:DWORD,OUT_SEGMENT_FINISH:DWORD


		.CODE	PASS2_TEXT

		EXTERNDEF	RELEASE_BLOCK:PROC,_err_abort:proc,FORREF2:PROC,FIXUPP_ERROR:PROC,ERR_ASCIZ_RET:PROC,ERR_RET:PROC
		EXTERNDEF	CONVERT_SUBBX_TO_EAX:PROC,RELOC_INSTALL:PROC,EXE_OUT_LDATA:PROC,RELEASE_DSBX:PROC,GET_SM_MODULE:PROC
		EXTERNDEF	OBJ_PHASE:PROC,WARN_RET:PROC,TIME_ERROR:PROC,SAY_VERBOSE:PROC,VERIFY_FAIL:PROC,DO_PE_RELOC:PROC
		EXTERNDEF	WARN_ASCIZ_RET:PROC

		EXTERNDEF	DATA_OUTSIDE_SEGMOD_ERR:ABS,UNRECOGNIZED_FIXUPP_FRAME_ERR:ABS,CANT_REACH_ERR:ABS,SHORT_ERR:ABS
		EXTERNDEF	LOC_FRAME_ERR:ABS,LOBYTE_ERR:ABS,UNREC_FIXUPP_ERR:ABS,START_ERR:ABS,START_CANT_REACH_ERR:ABS
		EXTERNDEF	START_IMPORT_ERR:ABS,RELOC_CONFLICT_ERR:ABS,BASE_RELOC_ERR:ABS,REC_TOO_LONG_ERR:ABS,START_ERR:ABS
		EXTERNDEF	NO_START_ERR:ABS,NEAR16_ERR:ABS,NEAR_IMPORT_ERR:ABS,DOING_SEGMOD_ERR:ABS


FIXUPP2		PROC
		;
		;
		;
		SETT	FINAL_FIXUPPS
		MOV	FIX2_TARG_TABLE,OFF FIX2_TARG_TABLE_NORMAL
if	fg_pe
		BITT	OUTPUT_PE
		JZ	L0$
		MOV	FIX2_TARG_TABLE,OFF FIX2_TARG_TABLE_PE
L0$:
endif

if	fg_norm_exe OR fg_segm
		CALL	DO_FARCALL_FIXUPPS
endif

if	any_overlays
		RESS	VECTORED_REFERENCE
endif

if	fg_segm
		BITT	OUTPUT_SEGMENTED
		MOV	ESI,OFF LOC_CALLTBL_PROT
		MOV	EDI,OFF LOC_10_PROT
		JNZ	L1$
endif
if	fg_pe
		BITT	OUTPUT_PE
		MOV	ESI,OFF LOC_CALLTBL_PE
		MOV	EDI,OFF LOC_10_PE
		JNZ	L1$
endif
		MOV	ESI,OFF LOC_CALLTBL_REAL
		MOV	EDI,OFF LOC_10_REAL
L1$:
		MOV	LOC_CALLTBL_PTR,ESI
		MOV	LOC_10,EDI

		;
		;STARTING PASS THROUGH DATA, SEGMENT BY SEGMENT
		;
		;HANDLE START ADDRESS IF ANY
		;
if	fg_rom
		XOR	AX,AX
		MOV	FIX2_PHASE_ADDR.LW,AX
		MOV	FIX2_PHASE_ADDR.HW,AX
endif
		CALL	HANDLE_START_ADDRESS
		MOV	CURNMOD_GINDEX,0
if	any_overlays
		BITT	DOING_OVERLAYS
		JZ	1$
		;
		;NEED TO MOVE START ADDRESS FROM EXEHEADER TO SLR_CODE_HEADER
		;
		MOV	BX,EXEHEADER._EXE_REG_IP
		MOV	CX,EXEHEADER._EXE_REG_CS
		MOV	AX,BX
		OR	AX,CX
		JZ	1$			;GOOD ENOUGH...
		LDS	SI,SLR_CODE_HEADER
		SYM_CONV_DS
		MOV	DX,[SI]._LD_SECOND_BLK
		ADD	SI,SIZE LDATA_HEADER_TYPE+$$SLR_MAIN
		CALL	SI_FIXER
		MOV	[SI],BX
		INC	SI
		INC	SI
		CALL	SI_FIXER
		MOV	[SI],CX
1$:

endif

if	fg_segm
		CALL	RC_STARTER
endif
		;
		;OK, START AT FIRST AREA, ONE SECTION AT A TIME PLEASE
		;
		MOV	EAX,FIRST_SECTION_GINDEX
		JMP	TEST_SECTION

SECTION_LOOP:
		MOV	CURN_SECTION_GINDEX,EAX

		CALL	OUT_NEW_SECTION 	;WE PROBABLY CARE...
SECL_2:
		MOV	ESI,CURN_SECTION_GINDEX
		XOR	EAX,EAX

		MOV	FIX2_LDATA_SEGMENT_GINDEX,EAX
		;
		;OK, START THROUGH MY SEGMODS
		;
		CONVERT	ESI,ESI,SECTION_GARRAY
		ASSUME	ESI:PTR SECTION_STRUCT

		MOV	ESI,[ESI]._SECT_FIRST_SEGMOD_GINDEX
		JMP	TEST_SEGMOD

if	fg_rom
SL_1:
		JMP	NEXT_SEG

SL_2:
		;
		;THIS IS A PHASE TARGET SEGMENT..., GET SOURCE VALUES
		;
		PUSHM	FIX2_LDATA_SEGMENT.OFFS,FIX2_LDATA_SEGMENT.SEGM
		LDS	SI,FIX2_SEG_PHASE	;SOURCE SEGMENT
		MOV	FIX2_LDATA_SEGMENT.OFFS,SI
		MOV	FIX2_LDATA_SEGMENT.SEGM,DS
		SYM_CONV_DS
		MOV	AX,FIX2_SEG_BASE.LW
		MOV	BX,FIX2_SEG_BASE.HW
		LEA	DI,FIX2_SEGMENT_STUFF
		MOV	CX,(SIZE SEGMENT_STRUCT+1)/2
		REP	MOVSW
		SUB	AX,FIX2_SEG_BASE.LW
		SBB	BX,FIX2_SEG_BASE.HW
		MOV	FIX2_PHASE_ADDR.LW,AX
		MOV	FIX2_PHASE_ADDR.HW,BX
		JMP	SL_3
endif

SEGMOD_LOOP:
		;
		;FIRST, SEE IF THIS IS A NEW SEGMENT
		;
		MOV	EBX,ESI
		MOV	FIX2_NEW_SEGMOD_GINDEX,ESI		;FOR COMMONS AND STACKS...

		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT

		MOV	EAX,[ESI]._SM_BASE_SEG_GINDEX
		MOV	ECX,FIX2_LDATA_SEGMENT_GINDEX

		CMP	ECX,EAX
		JZ	SAME_SEG

NEW_SEG:
		MOV	EAX,FIX2_LDATA_SEGMENT_GINDEX

		TEST	EAX,EAX
		JZ	NO_OLD_SEG

		CALL	OUT_SEGMENT_FINISH

NO_OLD_SEG:
		;
		;ANOTHER SEGMENT...
		;
		MOV	ESI,[ESI]._SM_BASE_SEG_GINDEX
		MOV	EDI,OFF FIX2_SEGMENT_STUFF

		MOV	FIX2_LDATA_SEGMENT_GINDEX,ESI
		CONVERT	ESI,ESI,SEGMENT_GARRAY
		ASSUME	ESI:PTR SEGMENT_STRUCT
		MOV	ECX,(SIZE SEGMENT_STRUCT+3)/4

		REP	MOVSD
if	fg_segm
		GETT	DL,RC_REORDER			;ARE WE REORDERING SEGMENTS FOR WINDOWS?
		MOV	EAX,FIX2_SEG_OS2_NUMBER

		TEST	DL,DL
		JZ	SL_3

		CONV_EAX_SEGTBL_ECX

		GETT	DL,RC_PRELOADS
		MOV	EAX,[ECX]._SEGTBL_FLAGS

		TEST	DL,DL
		JNZ	NOS_1
		;
		;WANT JUST NON-PRELOADS
		;
		TEST	AL,MASK SR_PRELOAD
		JZ	SL_3

		GETT	AL,RC_REORDER_SEGS

		TEST	AL,AL
		JZ	SL_3
SKIP_THIS:
		XOR	ECX,ECX
		MOV	EDX,FIX2_LDATA_SEGMENT_GINDEX
		MOV	ESI,EBX
		MOV	FIX2_LDATA_SEGMENT_GINDEX,ECX

ST_1:
		MOV	ECX,ESI
		CONVERT	ESI,ESI,SEGMOD_GARRAY	;SKIP TILL BASE SEGMENT IS DIFFERENT
		ASSUME	ESI:PTR SEGMOD_STRUCT

		MOV	EBX,[ESI]._SM_BASE_SEG_GINDEX
		MOV	ESI,[ESI]._SM_NEXT_SEGMOD_GINDEX

		CMP	EDX,EBX
		JNZ	TS_1

		TEST	ESI,ESI
		JNZ	ST_1

		JMP	TEST_SEGMOD

TS_1:
		MOV	ESI,ECX
		JMP	TEST_SEGMOD

NOS_1:
		;
		;WANT JUST PRELOADS
		;
		TEST	AL,MASK SR_PRELOAD
		JZ	SKIP_THIS

		GETT	AL,RC_REORDER_SEGS

		TEST	AL,AL
		JZ	SKIP_THIS
endif
if	fg_rom
		TEST	FIX2_SEG_ORDER_FLAG,MASK DEF_PHASEE
		JNZ	SL_1
		TEST	FIX2_SEG_ORDER_FLAG,MASK DEF_PHASE_TARG
		JNZ	SL_2
endif

SL_3:
		;
		;TELL OUTPUTTERS NEW SEGMOD COMING
		;
		CALL	OUT_NEW_SEGMENT

		CONVERT	ESI,EBX,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT

SAME_SEG:
		MOV	EAX,ESI
		MOV	EDI,OFF FIX2_SEGMOD_STUFF

		MOV	ECX,(SIZE SEGMOD_STRUCT+3)/4
		MOV	LDATA_SEGMOD_GINDEX,EBX

		REP	MOVSD

		CALL	GET_SM_MODULE

		;
		;TELL OUTPUTTERS NEW SEGMOD COMING
		;

		MOV	CURNMOD_GINDEX,EAX

if	0;debug
		MOV	ECX,FIX2_LDATA_SEGMENT_GINDEX
		CONVERT	ECX,ECX,SEGMENT_GARRAY
		ASSUME	ECX:PTR SEGMENT_STRUCT
		MOV	AL,DOING_SEGMOD_ERR

		ADD	ECX,SEGMENT_STRUCT._SEG_TEXT
		CALL	WARN_ASCIZ_RET
endif
		CALL	OUT_NEW_SEGMOD

		CALL	RELINK_DATA_BACKWARDS

		XOR	EAX,EAX
		MOV	ESI,FIX2_SM_FIRST_DAT

		MOV	FIX2_SM_LAST_DAT,EAX	 	;NO FORREFS HERE...
		JMP	LDATA_TEST

SM_FIRST_FORREF:
		MOV	FIX2_SM_FIRST_DAT,ESI
		JMP	SFF_RET

		ASSUME	ESI:PTR LDATA_HEADER_TYPE
SM_LINK_FORREF:
		;
		MOV	EDI,FIX2_SM_LAST_DAT
		ASSUME	EDI:PTR LDATA_HEADER_TYPE

		TEST	EDI,EDI
		JZ	SM_FIRST_FORREF

		MOV	[EDI]._LD_NEXT_LDATA,ESI
SFF_RET:
		MOV	FIX2_SM_LAST_DAT,ESI
		XOR	EAX,EAX

		MOV	EBX,[ESI]._LD_NEXT_LDATA
		MOV	[ESI]._LD_NEXT_LDATA,EAX

		MOV	ESI,EBX
		JMP	LDATA_TEST

		ASSUME	EDI:NOTHING
SM_DATA_LOOP:
		;
		;IF FORREF, SIMPLY LINK IT IN FOR NOW, CANNOT RELEASE
		;
		MOV	AL,[ESI]._LD_TYPE

		TEST	AL,MASK BIT_FI
		JNZ	SM_FIXUPP

		TEST	AL,MASK BIT_FR
		JNZ	SM_LINK_FORREF
		;
		;MUST BE A DATA RECORD, FLUSH ANY ALREADY IN THERE...
		;
		CALL	SM_FLUSH_LDATA
		;
		;NOW LOAD DATA RECORD PROPERLY, LIKE IN FIXUPP
		;
		MOV	EAX,[ESI]._LD_BLOCK_BASE
		MOV	EDI,OFF FIX2_LDATA_STUFF
		ASSUME	EDI:PTR LDATA_HEADER_TYPE

		MOV	FIX2_LDATA_BASE,EAX		;LDATA_LOG SET HERE
		MOV	EBX,DPTR [ESI]._LD_LENGTH

		MOV	[EDI]._LD_BLOCK_BASE,EAX
		MOV	ECX,[ESI]._LD_NEXT_LDATA

		MOV	DPTR [EDI]._LD_LENGTH,EBX
		AND	EBX,0FFFFH

		MOV	EAX,[ESI]._LD_OFFSET
		MOV	[EDI]._LD_NEXT_LDATA,ECX

		MOV	[EDI]._LD_OFFSET,EAX
		ADD	ESI,SIZEOF LDATA_HEADER_TYPE

		MOV	AL,FIX2_LD_TYPE
		ADD	EBX,ESI

		ASSUME	ESI:NOTHING,EDI:NOTHING

		MOV	FIX2_LDATA_PTR,ESI
		MOV	FIX2_LDATA_EOR,EBX
		;
		;CHECK FOR OVERLAPPED RECORD
		;
		TEST	AL,MASK BIT_CONT
		JZ	LDATA_LOADED

		CALL	LOAD_LDATA_SPEC

LDATA_LOADED:
		MOV	EAX,FIX2_LD_OFFSET
		MOV	EBX,FIX2_SM_START

		ADD	EAX,EBX

		MOV	FIX2_LDATA_LOC,EAX
		;
		;HERE WE CHECK FOR RELOCATION CONFLICTS...
		;
		CALL	RELOCATION_CHECK

		MOV	ESI,FIX2_LD_NEXT_LDATA
LDATA_TEST:
		TEST	ESI,ESI
		JNZ	SM_DATA_LOOP

		CALL	SM_FLUSH_LDATA		;IF THERE, FLUSH IT
		;
		;NOW PROCESS ANY FORREF RECORDS LINKED HERE
		;
		MOV	EAX,FIX2_SM_LAST_DAT

		TEST	EAX,EAX			 ;ANY THERE?
		JZ	SM_FORREFS_DONE

		CALL	DOFORREFS
SM_FORREFS_DONE:
		;
		;OK, THAT FINISHES THIS SEGMOD, SIGNAL OUTPUTTERS
		;
		CALL	OUT_SEGMOD_FINISH
		;
NEXT_SEGMOD:
		MOV	ESI,FIX2_SM_NEXT_SEGMOD_GINDEX
TEST_SEGMOD:
		;
		;IF SEGMOD DOESN'T EXIST, WE ARE DONE
		;
		TEST	ESI,ESI
		JNZ	SEGMOD_LOOP
SM_DONE:
		;
		;IF A SEGMENT IS ACTIVE, DO END-OF-SEGMENT
		;
		MOV	EAX,FIX2_LDATA_SEGMENT_GINDEX

		TEST	EAX,EAX
		JZ	SMD_1

		CALL	OUT_SEGMENT_FINISH
SMD_1:
if	fg_rom
		TEST	FIX2_SEG_ORDER_FLAG,MASK DEF_PHASEE
		JZ	SMD_1
		;
		;RESET STUFF BACK TO ORIGINAL SEGMENT
		;
		POPM	DS,SI
		MOV	FIX2_LDATA_SEGMENT.OFFS,SI
		MOV	FIX2_LDATA_SEGMENT.SEGM,DS
		SYM_CONV_DS
		FIXES
		LEA	DI,FIX2_SEGMENT_STUFF
		MOV	CX,(SIZE SEGMENT_STRUCT+1)/2
		REP	MOVSW
;		LDS	SI,FIX2_SEG_FIRST_SEGMOD
		MOV	FIX2_PHASE_ADDR.LW,CX
		MOV	FIX2_PHASE_ADDR.HW,CX
		MOV	HIGH_WATER.LW,CX
		MOV	HIGH_WATER.HW,CX
SMD_1:
endif
		;
		;END OF SECTION, SIGNAL IT
		;
		MOV	CURNMOD_GINDEX,0

		CALL	OUT_END_OF_SECTION
if	fg_segm
		GETT	AL,RC_REORDER
		GETT	CL,RC_PRELOADS

		TEST	AL,AL
		JZ	NEXT_SECTION

		TEST	CL,CL
		JZ	NO_MORE_RC

		RESS	RC_PRELOADS
		JMP	SECL_2

NO_MORE_RC:
		RESS	RC_REORDER

endif

NEXT_SECTION:
		;
		;OK, TRY FOR NEXT SECTION THIS AREA
		;
		MOV	EAX,CURN_SECTION_GINDEX
		CONVERT	EAX,EAX,SECTION_GARRAY
		ASSUME	EAX:PTR SECTION_STRUCT

		MOV	EAX,[EAX]._SECT_NEXT_SECTION_GINDEX

TEST_SECTION:
		TEST	EAX,EAX
		JNZ	SECTION_LOOP
EOS:
		CALL	OUT_END_OF_SEGMENTS
		XOR	EAX,EAX
		MOV	CURNMOD_GINDEX,EAX
		RET

		ASSUME	EAX:NOTHING

SM_FIXUPP:
		;
		;OK, LOAD/LOCK FIXUPP RECORD FOR EASY ACCESS...
		;
		CALL	LOAD_LOCK_FIXUPP	;DS:SI IS FIXUPP RECORD
		CALL	DOFIXUPPS		;DO TRANSFORMS

		MOV	ESI,FIX2_FH_NEXT_FIXUPP
		JMP	LDATA_TEST

FIXUPP2		ENDP


DOFORREFS	PROC	NEAR
		;
		;GO THROUGH LIST OF FORREF RECORDS
		;
		MOV	ESI,FIX2_SM_FIRST_DAT	;FIRST FORREF RECORD
SM_FORREF_LOOP:
		CALL	LOAD_LOCK_FIXUPP	;DS:SI IS FORREF RECORD
		CALL	FORREF2
		CALL	RELEASE_FIXUPP
		MOV	ESI,FIX2_FH_NEXT_FIXUPP

		TEST	ESI,ESI
		JNZ	SM_FORREF_LOOP

		RET

DOFORREFS	ENDP


		ASSUME	ESI:PTR FIXUPP_HEADER_TYPE

LOAD_LOCK_FIXUPP	PROC	NEAR
		;
		;DS:SI POINTS TO RECORD
		;FIX2_FIXUPP_EOR IS END OF RECORD
		;
		MOV	EAX,[ESI]._FH_BLOCK_BASE
		MOV	EDI,OFF FIX2_FIXUPP_STUFF
		ASSUME	EDI:PTR FIXUPP_HEADER_TYPE

		MOV	FIX2_FIXUPP_BASE,EAX
		MOV	EBX,DPTR [ESI]._FH_LENGTH

		MOV	[EDI]._FH_BLOCK_BASE,EAX
		MOV	DPTR [EDI]._FH_LENGTH,EBX

		MOV	ECX,[ESI]._FH_NEXT_FIXUPP
		AND	EBX,0FFFFH

		MOV	[EDI]._FH_NEXT_FIXUPP,ECX
		ADD	ESI,SIZEOF FIXUPP_HEADER_TYPE

		ASSUME	ESI:NOTHING,EDI:NOTHING

		MOV	CL,FIX2_FH_TYPE
		ADD	EBX,ESI

		AND	CL,MASK BIT_CONT
		JNZ	L1$

		MOV	FIX2_FIXUPP_EOR,EBX

		RET

L1$:
		SUB	EBX,ESI

		LEA	ECX,[EAX + PAGE_SIZE]		;NEXT LOGICAL BLOCK #
		MOV	EDI,OFF TEMP_FIXUPP_RECORD

		SUB	ECX,ESI
		MOV	EDX,[EAX]			;USAGE COUNTER

		SUB	EBX,ECX		;SAVE THIS #
		DEC	EDX

		SHR	ECX,2
		MOV	[EAX],EDX

		REP	MOVSD

		MOV	ESI,[EAX+4]
		LEA	ECX,[EBX+3]

		TEST	EDX,EDX
		JNZ	L2$

		CALL	RELEASE_BLOCK

L2$:
		MOV	EAX,ESI
		LEA	EDX,[EDI+EBX]

		MOV	EBX,[ESI]
		ADD	ESI,BLOCK_BASE

		SHR	ECX,2
		DEC	EBX

		REP	MOVSD

		MOV	[EAX],EBX
		JNZ	L3$

		CALL	RELEASE_BLOCK

L3$:
		MOV	FIX2_FIXUPP_BASE,ECX	;NO BLOCK TO UNLOCK...
		MOV	FIX2_FIXUPP_EOR,EDX

		MOV	ESI,OFF TEMP_FIXUPP_RECORD
		RET

LOAD_LOCK_FIXUPP ENDP


LOAD_LDATA_SPEC PROC	NEAR
		;
		;THIS GUY IS SPLIT OVER TWO BLOCKS, MOVE HIM TO LOCAL STORAGE
		;
		MOV	EBX,DPTR FIX2_LD_LENGTH
		MOV	EAX,FIX2_LD_BLOCK_BASE

		AND	EBX,0FFFFH
		MOV	EDI,OFF TEMP_DATA_RECORD

		CMP	EBX,MAX_LEDATA_LEN+32
		JA	L5$

		LEA	ECX,[EAX + PAGE_SIZE]
		MOV	FIX2_LDATA_PTR,EDI

		SUB	ECX,ESI
		MOV	EDX,[EAX]			;USAGE COUNTER

		SUB	EBX,ECX		;SAVE THIS #

		SHR	ECX,2
		DEC	EDX

		REP	MOVSD

		MOV	ESI,[EAX+4]
		LEA	ECX,[EBX+3]

		MOV	[EAX],EDX
		JNZ	L1$

		CALL	RELEASE_BLOCK

L1$:
		MOV	EAX,ESI
		LEA	EDX,[EDI+EBX]

		MOV	EBX,[ESI]
		ADD	ESI,BLOCK_BASE

		SHR	ECX,2
		DEC	EBX

		REP	MOVSD

		MOV	[EAX],EBX
		JNZ	L3$

		CALL	RELEASE_BLOCK

L3$:

		MOV	FIX2_LDATA_EOR,EDX
		MOV	FIX2_LDATA_BASE,ECX

		RET

L5$:
		MOV	AL,REC_TOO_LONG_ERR
		push	EAX
		call	_err_abort

LOAD_LDATA_SPEC ENDP


SM_FLUSH_LDATA	PROC	NEAR
		;
		;IF LDATA EXISTS, SEND IT OFF TO OTHER PROCESSOR
		;
		MOV	EAX,FIX2_LDATA_PTR

		TEST	EAX,EAX
		JZ	L99$

		CALL	EXE_OUT_LDATA		;OMF, HEX, EXE, DEBUG, ETC

		XOR	ECX,ECX
		MOV	EAX,FIX2_LDATA_BASE

		MOV	FIX2_LDATA_BASE,ECX
		MOV	FIX2_LDATA_PTR,ECX

		TEST	EAX,EAX
		JZ	L99$

		DEC	DPTR [EAX]
		JZ	RELEASE_BLOCK
L99$:
		RET

SM_FLUSH_LDATA	ENDP


RELEASE_FIXUPP	PROC	NEAR
		;
		;UNLOOSE THAT RECORD
		;
		MOV	EAX,FIX2_FIXUPP_BASE

		TEST	EAX,EAX
		JZ	L9$

		DEC	DPTR [EAX]
		JZ	RELEASE_BLOCK
L9$:
		RET

RELEASE_FIXUPP	ENDP


if	fg_segm

DO_FIXIMPORT	PROC	NEAR
		;
		;WE ARE ACCESSING AN IMPORTED ITEM...
		;
		;THIS BECOMES A RELOCATION ITEM,
		;SELF-REL IS ILLEGAL, ETC
		;
		MOV	EAX,FIX2_TOFFSET
		MOV	EBX,FIX2_OFFSET

		MOV	CL,FIX2_SEG_TYPE
		MOV	EDI,FIX2_LDATA_PTR

		AND	ECX,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	L1$			;TRY IGNORING THEM... FOR MICRORIM (LINK-COMPATIBLE...)

		CMP	FIX2_IMP_MODULE,ECX
		JZ	L5$			;FLOAT CONSTANT

		CALL	IMP_CALLTBL[ESI*4]
L1$:
		JMP	FIX_UNDEF_RET

L5$:
		CMP	ESI,34/2		;LOC_9
		JNZ	L51$
L50$:
		ADD	WPTR [EDI+EBX],AX
		ADD	EDI,EBX

		MOV	EAX,FIX2_LDATA_LOC
		MOV	ECX,0705H		;ADDITIVE, OS FIXUP

		ADD	EAX,EBX			;TARGET LOGICAL ADDRESS
		MOV	EDX,FIX2_IMP_OFFSET	;OS FIXUP NUMBER

		XOR	EBX,EBX

		;ES:DI IS PHYS_PTR
		;AX IS OFFSET IN SEGMENT
		;BX IS _RL_IMP_OFFSET
		;CL IS FIXUPP TYPE
		;CH IS FIXUPP FLAGS
		;DX IS _RL_IMP_MODULE
		;
		CALL	RELOC_INSTALL	;DO RELOCATION

		JMP	FIX_UNDEF_RET

L51$:
		CMP	ESI,42/2		;LOC_13
		JZ	L50$
		CALL	BAD_MYLOC

		JMP	FIX_UNDEF_RET

DO_FIXIMPORT	ENDP

endif

FIX_UN_A:	JMP	FIX_UNDEF_RET

FCR:		JMP	FIX_CANT_REACH


DOFIXUPPS	PROC	NEAR
		;
		;
		;
		CALL	DOF_PRELIM
		;
		;SO, GO AHEAD AND DO FIXUPP
		;

DOFIXUPPS_MODEND_A::
		PUSH	ESI
		JC	FIX_UN_A		;UNDEFINED SYMBOL, IGNORE

		MOV	ESI,FIX2_LOC
		MOV	EDI,LOC_CALLTBL_PTR

		GETT	AL,OUTPUT_PE
		GETT	CL,OUTPUT_SEGMENTED

		TEST	AL,AL
		JNZ	DOF_PE

		TEST	CL,CL
		JZ	DOF_REAL

		MOV	EAX,FIX2_OS2_TFLAGS

		TEST	EAX,MASK SR_1
		JNZ	DO_FIXIMPORT

		MOV	EAX,FIX2_OS2_TNUMBER	;TARGET SEGMENT MUST EQUAL
		MOV	ECX,FIX2_OS2_FNUMBER	;FRAME SEGMENT

		CMP	EAX,ECX
		JNZ	FCR			;FIX_CANT_REACH

		MOV	CL,FIX2_TTYPE
		MOV	EAX,FIX2_TOFFSET

		AND	CL,MASK SEG_ASEG
		JZ	DOF_CONT

		SUB	EAX,FIX2_OS2_FNUMBER
		JMP	DOF_CONT

if	fg_pe

DOF_PE:
		MOV	EAX,FIX2_TOFFSET
		JMP	DOF_CONT

endif

DOF_REAL:
		MOV	EAX,FIX2_OS2_TNUMBER
		MOV	EBX,FIX2_OS2_FNUMBER

		SUB	EAX,EBX
		JC	FIX_CANT_REACH1

		CMP	EAX,64K
		JAE	FIX_ERR6		;MAYBE OUT-OF-RANGE
FIX_ERR6_OK:
		MOV	ECX,LOC_10
		MOV	EAX,FIX2_TOFFSET

		CMP	ECX,OFF LOC_10_PROT
		JZ	DR_9
DR_8:
		SUB	EAX,EBX
DR_9:

DOF_CONT:
		MOV	CL,FIX2_LD_TYPE
		LEA	ESI,[ESI*4+EDI]

		AND	CL,MASK BIT_LI		;CAN'T CHECK LIDATA TYPES TILL LATER...
		JNZ	L29$

		MOV	EDI,FIX2_OFFSET
		MOV	ECX,FIX2_LDATA_LOC	;IS THIS COLLIDING WITH A PREVIOUS FIXUPP?

		ADD	EDI,ECX
		MOV	ECX,FIX2_STACK_DELTA

		ADD	EDI,ECX
		MOV	ECX,FIX2_SM_START

		SUB	EDI,ECX
		MOV	ECX,RELOC_HIGH_WATER

		CMP	ECX,EDI
		MOV	FIX2_RELOC_OFFSET,EDI	;USED BY FARCALLTRANSLATE

		JA	L2$
L29$:
		;
		;BX IS FIX2_OFFSET
		;CX:AX IS OFFSET WITHIN SEGMENT
		;DX IS FIX2_FRAME.HW
		;
		MOV	EDI,FIX2_LDATA_PTR	;PHYSICAL ADDRESS
		MOV	EBX,FIX2_OFFSET

		CALL	DPTR [ESI]

FIX_UNDEF_RET::
		POP	ESI
		MOV	EDI,FIX2_FIXUPP_EOR

		CMP	EDI,ESI
		JA	DOFIXUPPS

		JNZ	F_OOPS
		;
		;OK, NOW RELEASE FIXUPP RECORD AND UNLOCK BLOCK
		;
		CALL	RELEASE_FIXUPP
		RET

F_OOPS:
		CALL	OBJ_PHASE


FIX_ERR6:
		;
		;ACTUALLY, THIS IS OK IF A 32-BIT OFFSET TYPE...
		;LIKE 25 OR 27
		;

		MOV	ECX,EAX
		MOV	AL,BPTR FIX2_LOC

		CMP	AL,18	;*2
		JZ	CHECK_64K

		CMP	AL,25	;*2
		JZ	FIX_ERR6_OK

		CMP	AL,27	;*2
		JZ	FIX_ERR6_OK

		CMP	AL,10	;*2
		JZ	FIX_ERR6_OK

		CMP	AL,29	;*2
		JZ	FIX_ERR6_OK

FIX_CANT_REACH::
		MOV	AL,CANT_REACH_ERR
		BITT	DOING_START_ADDRESS
		JZ	FCR_4
		MOV	AL,START_ERR
		MOV	FIX2_FTYPE,MASK SEG_CLASS_IS_CODE + MASK SEG_RELOC
		MOV	FIX2_TTYPE,MASK SEG_CLASS_IS_CODE + MASK SEG_RELOC
FCR_4:
		CALL	FIX_ERROR
		JMP	FIX_UNDEF_RET

if	fg_norm_exe

FIX_CANT_REACH1:
		;
		;FRAME LARGER, TRY ADDING OFFSET IN AS LAST RESORT
		;
if	fg_dosx
		CMP	EXETYPE_FLAG,DOSX_EXE_TYPE		;IGNORE IF DOSX...
		JZ	FIX_ERR6_OK
endif
		MOV	EAX,FIX2_TOFFSET

		SUB	EAX,EBX
		JC	FIX_CANT_REACH

		JMP	FIX_ERR6_OK

endif

L2$:
		PUSHM	SI,DX,CX,BX,AX
		;
		;NEED AX = FIRST BIT TO CHECK, CX = # OF BITS
		;
		XCHG	AX,DI
		SHR	SI,1
		MOV	CL,LOC_SIZE[SI]
		XOR	CH,CH
		CALL	SPECIAL_RELOC_CHECK
		POPM	AX,BX,CX,DX,SI
		JMP	L29$

if	fg_norm_exe

CHECK_64K:
		CMP	ECX,64K
		JNZ	FIX_CANT_REACH
		JMP	FIX_ERR6_OK

endif

L5$:
		JMP	FIX_UNDEF_RET

DOFIXUPPS	ENDP


DOFIXUPPS_MODEND	EQU	(DOFIXUPPS_MODEND_A)


DOF_PRELIM	PROC	NEAR
		;
		;
		;
		MOV	EAX,[ESI]
		ADD	ESI,4

		MOV	ECX,EAX
		MOV	EDX,EAX

		SHR	ECX,16
		AND	EAX,0FFFFH

		SHR	EDX,26
		AND	ECX,1024-1

		MOV	FIX2_LOC,EDX
		MOV	FIX2_OFFSET,ECX

DOF_PRELIM	ENDP

; Returns: C error
PARSE_FIXUPP2	PROC	NEAR
		;
		;NOW SET UP STUFF FOR FRAME AND TARGET	- PRESERVE SI
		;
		;
		;POSSIBLE TARGETS ARE:
		;	0	SEGMENT (1 BYTE) DELTA=0
		;	1	GROUP	(1 BYTE) DELTA=8
		;	2	SYMBOL	(1 BYTE) DELTA=48
		;	3	ABSOLUTE(1 BYTE) DELTA=0
		;
		;  +4	MEANS	2 BYTE INDEX INSTEAD OF 1
		;    08-0F	GROUPS 1 THRU 8
		;    10-3F	SYMBOLS 1 THRU 48
		;
		;   HIGH 2 BITS
		;	00	NO OFFSET
		;	01	1 BYTE OFFSET
		;	10	2 BYTE OFFSET
		;	11	3 BYTE OFFSET
		;
		MOV	EBX,EAX
		MOV	ECX,[ESI]

		ADD	ESI,4
		XOR	EDX,EDX

		TEST	EAX,1000H
		JZ	L2$

		MOV	EDX,[ESI]
		ADD	ESI,4

L2$:
		AND	AH,0FH
		MOV	FIX2_TOFFSET,EDX

		MOV	BPTR FIX2_TT,AH
		MOV	FIX2_TINDEX,ECX
		;
		;PARSE STUFF FOR FRAME
		;
		CMP	AL,4
		JB	L25$

		CMP	AL,6
		JB	L3$

		MOV	ECX,EAX

		AND	ECX,07FH
		MOV	AL,1

		MOV	ECX,GROUP_PTRS[ECX*4-6*4]
		JMP	L3$


L25$:
		MOV	ECX,[ESI]
		ADD	ESI,4

L3$:
		MOV	EDX,FIX2_TT
		PUSH	ESI

		MOV	EBX,FIX2_TARG_TABLE	;IN CODE SEGMENT...
		MOV	BPTR FIX2_FF,AL

		MOV	EAX,FIX2_TINDEX
		MOV	FIX2_FINDEX,ECX
		;
		;NOW PROCESS STUFF
		;
		CALL	DPTR [EBX+EDX*4]

		MOV	FIX2_TTYPE,AL
		JC	L99$			;UNDEFINED SYMBOL

		GETT	AL,OUTPUT_PE
		MOV	EBX,FIX2_FF

		OR	AL,AL
		JNZ	L99$

		MOV	EAX,FIX2_FINDEX

		CALL	FIX2_FRAME_TABLE[EBX*4]

		MOV	FIX2_FTYPE,AL
		JC	L99$			;UNDEFINED SYMBOL

		MOV	FIX2_OS2_FNUMBER,ECX
;		MOV	FIX2_OS2_FFLAGS,EDX
if	any_overlays
		BITT	VECTORED_REFERENCE
		JZ	4$
		;
		;IF FRAME IS BELOW VECTOR TABLE, AND WITHIN 64K OF END OF TABLE, USE IT, ELSE USE VECTOR_TABLE_ADDRESS
		;
		RESS	VECTORED_REFERENCE
		MOV	AX,END_VECTOR_TABLE.LW
		MOV	BX,END_VECTOR_TABLE.HW
		SUB	AX,CX
		SBB	BX,DX
		JZ	4$
		MOV	AX,VECTOR_TABLE_ADDRESS.LW
		MOV	DX,VECTOR_TABLE_ADDRESS.HW
		MOV	FIX2_FFRAME.LW,AX
		MOV	FIX2_FFRAME.HW,DX
endif
L4$:
		MOV	AL,FIX2_TTYPE
		POP	ESI

		TEST	AL,MASK SEG_CONST	;IF TARG IS CONSTANT, FORCE FRAME TO MATCH
		JNZ	L9$				;CHECK NORMALLY...

		RET

L99$:
		POP	ESI

		RET

L9$:
		MOV	EAX,FIX2_OS2_TNUMBER
		MOV	ECX,FS_TYPE_TARG

		MOV	FIX2_OS2_FNUMBER,EAX
		MOV	AL,MASK SEG_ASEG

		MOV	FIX2_FF,ECX		;=FRAME TARG...
		MOV	FIX2_FTYPE,AL

		RET

PARSE_FIXUPP2	ENDP


LOC_0_PROT	PROC	NEAR
		;
		;SELF-RELATIVE SHORT JUMP
		;
		;CX:AX IS OFFSET OF TARGET FROM FRAME
		;
		;BX IS FIX2_OFFSET
		;CX:AX IS OFFSET WITHIN SEGMENT
		;DX IS FIX2_FRAME.HW
		;
		;FIRST, SEE IF CURRENT LOCATION IS IN FRAME
		;
		MOV	ESI,FIX2_OS2_TNUMBER
		MOV	EDX,FIX2_SEG_OS2_NUMBER

		CMP	EDX,ESI
		JNZ	FIX_LOC_FRAME
LOC_0_PE::
		MOV	EDX,FIX2_LDATA_LOC
		SUB	EAX,EBX			;OUCH!

		SUB	EAX,EDX
		JMP	LOC_0_CONT

LOC_0_PROT	ENDP


LOC_0_REAL	PROC	NEAR
		;
		;
		;
		MOV	ESI,FIX2_LDATA_LOC
		MOV	EDX,FIX2_FFRAME

		SUB	ESI,EDX

		ADD	ESI,EBX

		CMP	ESI,64K
		JAE	FIX_LOC_FRAME
		;
		;OK, SO, TOFFSET-CURLOC-1
		;
		SUB	EAX,ESI
;		JMP	LOC_0_CONT

LOC_0_REAL	ENDP


LOC_0_CONT	PROC	NEAR
		;
		;
		;`
		DEC	EAX
		JS	LT_0

		CMP	EAX,128
		JNC	SHORT_ERROR

		ADD	[EDI+EBX],AL

		RET


SHORT_ERROR:
		MOV	AL,SHORT_ERR
		JMP	FIX_ERROR

LT_0:
		CMP	EAX,-128
		JC	SHORT_ERROR
LOC_0_OK::
		ADD	[EDI+EBX],AL

		RET

LOC_0_CONT	ENDP


LOC2_8		PROC	NEAR
		;
		;LO-BYTE
		;
		;CX:AX IS OFFSET FROM FRAME
		;
		MOV	DL,[EDI+EBX]
		GETT	CL,CHECK_LO_BYTE

		ADD	DL,AL
		TEST	CL,CL

		MOV	[EDI+EBX],DL
		JZ	L1$

		OR	AH,AH
		JZ	L1$

		CMP	EAX,-128
		JC	LOC2_8_ERR
L1$:
		RET

LOC2_8_ERR:
		MOV	AL,LOBYTE_ERR
FIX_ERROR::
		CALL	FIXUPP_ERROR
		RET

FIX_LOC_FRAME::
		MOV	AL,LOC_FRAME_ERR
		CALL	FIXUPP_ERROR
		RET

LOC2_8		ENDP


LOC_1_PROT	PROC	NEAR
		;
		;SELF-RELATIVE NEAR JUMP
		;
		;CX:AX IS OFFSET OF TARGET FROM FRAME
		;
		;BX IS FIX2_OFFSET
		;CX:AX IS OFFSET WITHIN SEGMENT
		;DX IS FIX2_FRAME.HW
		;
		;FIRST, SEE IF CURRENT LOCATION IS IN FRAME
		;
		MOV	EDX,FIX2_LDATA_LOC
		SUB	EAX,EBX

		MOV	ESI,FIX2_OS2_TNUMBER
		SUB	EAX,EDX

		MOV	ECX,FIX2_SEG_OS2_NUMBER
		SUB	EAX,2

		CMP	ESI,ECX
		JNZ	FIX_LOC_FRAME
		;
		;IF BOTH WITHIN FRAME, RANGE MUST BE OK...
		;
		ADD	WPTR [EDI+EBX],AX
		RET

LOC_1_PROT	ENDP


LOC_1_REAL	PROC	NEAR
		;
		;
		;
		MOV	ESI,FIX2_LDATA_LOC
		MOV	EDX,FIX2_FFRAME

		SUB	ESI,EDX

		ADD	ESI,EBX
		SUB	EAX,2

		CMP	ESI,64K
		JAE	FIX_LOC_FRAME
		;
		;OK, SO, TOFFSET-CURLOC-1
		;
		SUB	EAX,ESI
		;
		;IF BOTH WITHIN FRAME, RANGE MUST BE OK...
		;
		ADD	WPTR [EDI+EBX],AX
		RET

LOC_1_REAL	ENDP


LOC_32SELF_PROT	PROC	NEAR
		;
		;SELF-RELATIVE 32-BIT JUMP...
		;
		;CX:AX IS OFFSET OF TARGET FROM FRAME
		;
		;BX IS FIX2_OFFSET
		;CX:AX IS OFFSET WITHIN SEGMENT
		;DX IS FIX2_FRAME.HW
		;
		;FIRST, SEE IF CURRENT LOCATION IS IN FRAME
		;
		MOV	ESI,FIX2_OS2_TNUMBER
		MOV	EDX,FIX2_SEG_OS2_NUMBER

		CMP	EDX,ESI
		JNZ	FIX_LOC_FRAME
LOC_32SELF_PE::
		MOV	EDX,FIX2_LDATA_LOC
		MOV	ECX,[EDI+EBX]

		SUB	EAX,EDX
		SUB	ECX,EBX

		ADD	EAX,ECX

		SUB	EAX,4

		MOV	[EDI+EBX],EAX

		RET


LOC_32SELF_PROT	ENDP


LOC_32SELF_REAL	PROC	NEAR
		;
		;
		;
		MOV	ESI,FIX2_LDATA_LOC
		MOV	EDX,FIX2_FFRAME

		SUB	ESI,EDX
		SUB	EAX,EBX
		;
		;OK, SO, TOFFSET-CURLOC-1
		;
		SUB	EAX,ESI
		MOV	ECX,[EDI+EBX]

		SUB	EAX,4

		ADD	EAX,ECX
		;
		;IF BOTH WITHIN FRAME, RANGE MUST BE OK...
		;
		MOV	[EDI+EBX],EAX

		RET

LOC_32SELF_REAL	ENDP


IMP_8		PROC	NEAR
		;
		;LO-BYTE
		;
		;DX:AX IS OFFSET FROM FRAME
		;
		MOV	DL,[EDI+EBX]
		MOV	ECX,400H 	;ADDITIVE, LOBYTE

		ADD	DL,AL	;CLEAR ANY OFFSET

		MOV	[EDI+EBX],DL
		JMP	DO_IMPORT

IMP_8		ENDP


LOC_13_PROT	PROC	NEAR
		;
		;16 BIT OFFSET SPECIAL
		;
		;IF NOT PROTMODE, AND TARGET IS LOADONCALL, USE POINTER
		;RELOC
		;
		CALL	KEEP_RELOC_OFFSET?
		JZ	LOC_9
LOC_131:
		MOV	ECX,5		;16 BIT OFFSET
		JMP	DO_INTERNAL

LOC_13_PROT	ENDP


KEEP_RELOC_OFFSET?	PROC	NEAR
		;
		;IS THE OFFSET RELOCATABLE, OR JUST SEGMENT?
		;
		MOV	DL,FIX2_SEG_TYPE
		MOV	ECX,FIX2_OS2_TNUMBER	;CONSTANT, LOSE OFFSET

		AND	DL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	L7$			;CODEVIEW, LOSE OFFSET

		TEST	ECX,ECX
		JZ	L71$

		MOV	DL,FIX2_TTYPE
		MOV	CL,EXETYPE_FLAG

		AND	DL,MASK SEG_ASEG
		JNZ	L7$
		;
		;IF EXETYPE > 2, KEEP POINTER (DOS4 AND UNKNOWN DON'T OPTIMIZE)
		;
		CMP	CL,WIN_SEGM_TYPE	;NOT OS/2 OR WINDOWS, RETAIN RELOCATABLE OFFSET
		JA	L8$				;EVEN IF NOT MOVABLE

		MOV	ESI,MOVABLE_MASK
		MOV	EDX,FIX2_OS2_TFLAGS

		TEST	ESI,EDX ;MOVABLE|DISCARD|IOPL
		JZ	L71$
		;
		;OK, ITS A 'MOVABLE' TYPE.
		;
		;IF WINDOWS, REAL MODE, WE KEEP ALL
		;
		GETT	CH,PROTMODE

		TEST	CH,CH
		JNZ	L1$

		CMP	CL,WIN_SEGM_TYPE
		JZ	L8$			;WINDOWS, YES, KEEP
L1$:
		;
		;PROTECTED MODE AND/OR OS/2, KEEP ONLY IF IOPL-NONCONFORMING-CODE REFERENCED
		;FROM ANYTHING OTHER THAN IOPL-NONCONFORMING-CODE
		;
;		TEST	DX,1 SHL SR_DPL		;IOPL?		;CAN ONLY GET HERE IF IOPL
;		JZ	8$			;NO, KEEP
		;
		;THEN USE MOVABLE OFFSET ONLY IF NONCONFORMING AND CODE ALSO...
		;
		AND	EDX,MASK SR_CONF+1	;CONFORMING OR DATA
		JNZ	L7$			;YES, IGNORE OFFSET
		;
		;OK, TARGET IS IOPL-NONCONFORMING-CODE
		;THROW AWAY OFFSET ONLY IF CURRENT SEGMENT IS SAME
		;
		MOV	ECX,FIX2_SEG_OS2_FLAGS
		MOV	EDX,1 SHL SR_DPL

		TEST	ECX,EDX
		JZ	L8$			;NOT IOPL, KEEP OFFSET

		AND	ECX,MASK SR_CONF+1

		RET

L8$:
		OR	CL,-1			;RETAIN OFFSET

		RET

L7$:
		CMP	AL,AL			;Z, USE INTERNAL, NON-MOVING
L71$:
		RET

KEEP_RELOC_OFFSET?	ENDP


if	fg_pe
LOC_9_PE:
		MOV	CL,FIX2_TTYPE

		AND	CL,MASK SEG_ASEG
		JZ	BAD_MYLOC
endif
LOC_13_REAL:
LOC_9:
		;
		;16-BIT OFFSET
		;
		ADD	WPTR [EDI+EBX],AX
		RET


if	fg_segm

IMP_9		PROC	NEAR
		;
		;16-BIT OFFSET
		;
		ADD	WPTR [EDI+EBX],AX
		MOV	ECX,005H 	;16-BIT OFFSET

		JZ	L2$

		OR	CH,4			;YES, ADDITIVE
L2$:
		JMP	DO_IMPORT

IMP_9		ENDP

endif


LOC2_12		PROC	NEAR
		;
		;HI-BYTE
		;
		ADD	[EDI+EBX],AH
		RET

LOC2_12		ENDP


LOC_11_PROT	PROC	NEAR
		;
		;16:16 POINTER
		;
		MOV	DL,FIX2_SEG_TYPE
		GETT	CL,FARCALLTRANSLATION_FLAG

		AND	DL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	L11_NORM

		TEST	CL,CL
		JZ	L5$

		MOV	DL,FIX2_SEG_TYPE

		AND	DL,MASK SEG_CLASS_IS_CODE
		JZ	L5$

		MOV	ESI,FIX2_OS2_TNUMBER
		MOV	EDX,FIX2_SEG_OS2_NUMBER

		CMP	EDX,ESI
		JNZ	L5$

		CALL	CHECK_9A

		JZ	FAR_CALL_COMMON


L5$:
		CALL	KEEP_RELOC_OFFSET?

		JZ	L11_NORM
LOC_111:
		MOV	ECX,3		;16:16
		JMP	DO_INTERNAL

LOC_11_PROT	ENDP


L11_NORM:
		ADD	WPTR [EDI+EBX],AX
		ADD	EBX,2
		;
		;PLUS WHATEVER ELSE IS NEEDED FOR RANGE CHECKING
		;
		XOR	EAX,EAX
		JMP	LOC_10


LOC_11_REAL	PROC	NEAR
		;
		;16:16 POINTER
		;
		GETT	CL,FARCALLTRANSLATION_FLAG
		MOV	DL,FIX2_SEG_TYPE

		TEST	CL,CL
		JZ	L11_NORM

		AND	DL,MASK SEG_CLASS_IS_CODE
		JZ	L11_NORM
		;
		;FRAME MUST MATCH FRAME OF LDATA_LOC
		;
		MOV	ESI,FIX2_SEG_FRAME
		MOV	EDX,FIX2_FFRAME

		CMP	ESI,EDX
		JNZ	L11_NORM

		CMP	FIX2_TFRAME,ESI
		JNZ	L11_NORM

		CALL	CHECK_9A
		JNZ	L11_NORM
		;
		;MAKE CX:AX 20-BIT REAL
		;
		ADD	EAX,FIX2_TFRAME
		JMP	FAR_CALL_COMMON

LOC_11_REAL	ENDP


FAR_CALL_COMMON PROC	NEAR
		;
		;
		;
		OR	ESI,ESI
		JNZ	FAR_JMP_COMMON
		;
		;NOP, PUSH CS, CALL NEAR
		;
		ADD	AX,WPTR [EDI+EBX]
		MOV	ECX,0E80EH

		MOV	WPTR [EDI+EBX],CX
		ADD	EBX,2

		MOV	ECX,FIX2_LDATA_LOC
		SUB	EAX,EBX

		SUB	EAX,ECX

		SUB	EAX,2

		MOV	WPTR [EDI+EBX],AX
		RET

FAR_JMP_COMMON:
		MOV	DX,WPTR [EDI+EBX]
		MOV	ECX,FIX2_LDATA_LOC

		ADD	ECX,EBX
		ADD	EAX,EDX

		SUB	EAX,ECX
		MOV	CL,90H

		SUB	EAX,2
		MOV	2[EDI+EBX],CL

		MOV	WPTR [EDI+EBX],AX
		RET

FAR_CALL_COMMON ENDP


CHECK_9A	PROC	NEAR
		;
		;**** MUST PRESERVE AX ****
		;
		;RETURNS NZ IF NO MATCH
		;SI=0 IF CALL, SI=1 IF JMP
		;
		MOV	CL,FIX2_SM_FLAGS_2

		AND	CL,MASK SM2_DATA_IN_CODE
		JNZ	L9$

		TEST	EBX,EBX
		JZ	L5$
CHECK_9AA:
		MOV	DL,BPTR [EBX+EDI-1]

		CMP	DL,9AH
		JNZ	L3$			;NOT A FAR CALL, TRY JUMP

		CALL	TEST_9A_RELOC

		MOV	DL,90H
		JNZ	L1$

		XOR	ESI,ESI
		MOV	BPTR [EDI+EBX-1],DL
L1$:
		RET


L3$:
		CMP	DL,0EAH
		JNZ	L9$
		CALL	TEST_9A_RELOC

		MOV	DL,0E9H
		JNZ	L4$

		MOV	BPTR [EBX+EDI-1],DL
		MOV	ESI,1
L4$:
		RET

L5$:
		;
		;THIS IS A BIT TRICKIER, WOULD BE NICE FOR FARCALL,
		;ABSOLUTELY NECESSARY FOR SINGLE-LEVEL OVERLAYS...
		;
		;ES:DI POINTS TO RECORD, BX IS OFFSET FROM RECORD
		;NEED TO CALCULATE ADDRESS RELATIVE FROM FIX2_SEGMENT_BASE
		;AND GO CHECK THAT BYTE...
		;
		PUSHM	EDI,EBX

		PUSH	EAX
		MOV	EDI,FIX2_LDATA_LOC

		MOV	EBX,FIX2_STACK_DELTA
		MOV	ECX,FIX2_SM_START

		ADD	EDI,EBX
		INC	ECX

		SUB	EDI,ECX
		JC	L8$

		MOV	EBX,EDI
		AND	EDI,PAGE_SIZE-1

		SHR	EBX,PAGE_BITS
		INC	EDI

		LEA	EBX,EXETABLE[EBX*4]
		CALL	CONVERT_SUBBX_TO_EAX

		MOV	EBX,EAX
		CALL	CHECK_9AA
L81$:
		POPM	EAX,EBX,EDI
L9$:
		RET

L8$:
		OR	ESI,-1
		JMP	L81$

CHECK_9A	ENDP


TEST_9A_RELOC	PROC	NEAR
		;
		;ECX & EDX ARE AVAILABLE
		;
		MOV	EDX,FIX2_RELOC_OFFSET
		MOV	ECX,RELOC_HIGH_WATER

		SUB	EDX,1
		JC	L9$

		CMP	ECX,EDX
		JBE	L9$

		MOV	CL,DL
		PUSH	EAX

		SHR	EDX,3		;BYTE #
		AND	CL,7

		ADD	EDX,RELOC_BITS
		MOV	AL,1

		SHL	AL,CL

		AND	AL,[EDX]
		POPM	EAX

		RET

L9$:
		CMP	BL,BL

		RET

TEST_9A_RELOC	ENDP


if	fg_segm

IMP_11		PROC	NEAR
		;
		;16:16 POINTER
		;
		MOV	ECX,[EDI+EBX]
		AND	EAX,0FFFFH

		ADD	EAX,ECX
		MOV	ECX,003H 	;16:16

		MOV	WPTR [EDI+EBX],AX
		JZ	L2$
		OR	CH,4			;YES, ADDITIVE
L2$:
		JMP	DO_IMPORT

IMP_11		ENDP

endif


LOC_DWORD_OFFSET1_PROT	PROC	NEAR
		;
		;32 BIT OFFSET SPECIAL
		;
if	fg_segm
		CALL	KEEP_RELOC_OFFSET?
		JZ	LOC_DWORD_OFFSET
LOC_LDO1:
		MOV	ECX,00DH 	;16 BIT OFFSET
		JMP	DO_INTERNAL

endif

LOC_DWORD_OFFSET1_PROT	ENDP



LOC_DWORD_OFFSET1_REAL:

LOC_DWORD_OFFSET:
		;
		;32-BIT OFFSET
		;
		ADD	[EDI+EBX],EAX

		RET

if	fg_pe

LOC_DWORD_OFFSET_PE	PROC	NEAR
		;
		;32-BIT OFFSET
		;
		MOV	ECX,[EDI+EBX]
		MOV	DL,FIX2_TTYPE

		ADD	ECX,EAX
		AND	DL,MASK SEG_ASEG

		MOV	[EDI+EBX],ECX
		JNZ	L9$

		MOV	EAX,FIX2_LDATA_LOC

		ADD	EAX,EBX
		JMP	DO_PE_RELOC
L9$:
		RET

LOC_DWORD_OFFSET_PE	ENDP
#endif

void _loc_dword_offset_tls(unsigned EAX, unsigned EBX, unsigned char *EDI)
{
    /* EAX: offset within segment
     * EBX: FIX2_OFFSET
     * EDI: physical address
     */
    // 32-BIT OFFSET
    unsigned ECX = *(unsigned *)(EDI + EBX) + EAX;
    if (FIX2_SEG_GINDEX)
    {
	PE_OBJECT_STRUCT *EDX = (PE_OBJECT_STRUCT *)FIX2_SEG_GINDEX->_SEG_PEOBJECT_GINDEX;
	ECX -= PE_BASE;

	/* Bugzilla 4275
	 * Seg faults with EDX == 0
	 * Caused by missing 'export' from an imported variable declaration
	 */
	if (!EDX)
	{
	    _err_abort(MISSING_EXPORT);
	}
	ECX -= EDX->_PEOBJECT_RVA;
    }
    *(unsigned *)(EDI + EBX) = ECX;
}

#if 0

endif

if	fg_segm

IMP_DWORD_OFFSET	PROC	NEAR
		;
		;32-BIT OFFSET
		;
		MOV	ECX,[EDI+EBX]

		ADD	EAX,ECX
		MOV	ECX,00DH

		MOV	[EDI+EBX],EAX
		JZ	L2$

		OR	CH,4			;YES, ADDITIVE
L2$:
		JMP	DO_IMPORT

IMP_DWORD_OFFSET	ENDP

endif

if	fg_segm

IMP_FWORD_PTR	PROC	NEAR
		;
		;16:32 POINTER
		;
		MOV	DX,WPTR [EDI+EBX+4]
		MOV	ECX,[EDI+EBX]

		ADD	EAX,ECX
		MOV	ECX,00BH 	;16:32

		MOV	[EDI+EBX],EAX
		JNZ	L1$

		AND	EDX,0FFFFH
		JZ	L2$
L1$:
		OR	CH,4
L2$:
		JMP	DO_IMPORT

IMP_FWORD_PTR	ENDP

endif


LOC_FWORD_PTR_PROT	PROC	NEAR
		;
		;16:32 POINTER
		;
if	fg_segm
		CALL	KEEP_RELOC_OFFSET?
		JZ	LFP_NORM
LOC_LFP1:
		MOV	ECX,00BH 	;16:32
		JMP	DO_INTERNAL

LFP_NORM:
endif

LOC_FWORD_PTR_PROT	ENDP


LOC_FWORD_PTR_REAL:

		MOV	ECX,[EDI+EBX]
		ADD	EBX,4

		ADD	ECX,EAX
		XOR	EAX,EAX

		MOV	[EDI+EBX-4],ECX
		JMP	LOC_10

if	fg_pe

LOC_10_PE	PROC	NEAR
		;
		;
		;
		MOV	AL,UNREC_FIXUPP_ERR
		CALL	FIXUPP_ERROR
		RET

LOC_10_PE	ENDP

endif


LOC_10_PROT	PROC	NEAR
		;
		;BASE
		;
if fg_segm
		;
		;segmented mode...
		;
		MOV	CX,WPTR [EDI+EBX]

		AND	ECX,0FFFFH
		JNZ	DI_101
DI_1011:
		CALL	KEEP_RELOC_OFFSET?

		MOV	DL,FIX2_SEG_TYPE
		JNZ	DI_103

		MOV	DH,FIX2_TTYPE
		MOV	EAX,FIX2_OS2_TNUMBER

		AND	DL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	LOC_10_DEBUG

		AND	DH,MASK SEG_ASEG
		JNZ	LOC_10_DEBUG_A

		TEST	EAX,EAX			;CONSTANT?
		JZ	LOC_10_DEBUG
DI_104:
		XOR	EAX,EAX
		MOV	ECX,0802H		;BASE, DON'T LOOK EVEN IF MOVABLE
		JMP	DO_INTERNAL

DI_103:
		MOV	ECX,002H
		JMP	DO_INTERNAL

DI_101:
		;
		;HMM, FOR FORTRAN WE NEED TO ACCEPT THIS...
		;
		ADD	FIX2_OS2_TNUMBER,ECX
		XOR	EDX,EDX

		MOV	WPTR [EDI+EBX],DX
		JMP	DI_1011

LOC_10_DEBUG_A:
		SHR	EAX,4
LOC_10_DEBUG:
		MOV	WPTR [EDI+EBX],AX

		RET

else
		MOV	EAX,FIX2_OS2_TNUMBER
		MOV	WPTR [EDI+EBX],AX
		RET

endif

LOC_10_PROT	ENDP


LOC_10_REAL	PROC	NEAR
		;
		;
		;
		MOV	CX,WPTR [EDI+EBX]
		MOV	EAX,FIX2_FFRAME

		SHR	EAX,4
		MOV	DL,FIX2_TTYPE

		ADD	EAX,ECX
		AND	DL,MASK SEG_RELOC

		MOV	WPTR [EDI+EBX],AX
		;
		;IF RELOCATABLE, CALL HANDLER...
		;
		JZ	LOC_10_RET

		MOV	DL,FIX2_SEG_TYPE
		GETT	CL,OUTPUT_COM_SYS

		AND	DL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	LOC_10_RET		;SKIP IF DEBUG RECORD

		TEST	CL,CL
		JNZ	BASE_ERROR

		MOV	EDX,EAX			;TARGET PARAGRAPH
		ADD	EDI,EBX

		AND	EDX,0FFFFH
		GETT	AL,CHAINING_RELOCS	;TRUE ONLY FOR /EXEPACK?

		MOV	ECX,802H 		;REAL-MODE (8) BASE (2)
		OR	AL,AL

		MOV	EAX,EBX
		JNZ	L1$
		MOV	CH,12			;REAL-MODE(8) ADDITIVE(4)
L1$:
		MOV	ESI,FIX2_LDATA_LOC
		XOR	EBX,EBX			;TARGET SEGMENT OFFSET

		ADD	EAX,ESI
		;
		;ES:DI IS PHYS_PTR
		;AX IS .LW OF OVERALL ADDRESS
		;BX IS TARGET SEGMENT OFFSET
		;CL IS FIXUPP TYPE
		;CH IS FIXUPP FLAGS
		;DX IS TARGET SEGMENT PARAGRAPH
		;
		JMP	RELOC_INSTALL

BASE_ERROR:
		MOV	AL,BASE_RELOC_ERR
		CALL	FIXUPP_ERROR
LOC_10_RET:
		RET

LOC_10_REAL	ENDP


if	fg_segm

IMP_10		PROC	NEAR
		;
		;
		;
		MOV	DX,WPTR [EDI+EBX]
		MOV	ECX,002H

		AND	EDX,0FFFFH
		JZ	L2$

		OR	CH,4
L2$:
		JMP	DO_IMPORT

IMP_10		ENDP
endif

if	fg_segm
BAD_MYLOC_IMP	PROC	NEAR

		MOV	AL,NEAR_IMPORT_ERR
		CALL	FIXUPP_ERROR
		RET

BAD_MYLOC_IMP	ENDP
endif

BAD_MYLOC		PROC	NEAR

		MOV	AL,UNREC_FIXUPP_ERR
		CALL	FIXUPP_ERROR
		RET

BAD_MYLOC		ENDP


TARG_SEGMOD_NORMAL	PROC	NEAR
		;
		;EAX IS SEGMOD GINDEX
		;
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		MOV	ECX,[EAX]._SM_START
		MOV	EDX,FIX2_TOFFSET

		MOV	EAX,[EAX]._SM_BASE_SEG_GINDEX
		ADD	EDX,ECX

		MOV	FIX2_SEG_GINDEX,EAX		;IN CASE OF TLS
		MOV	FIX2_TOFFSET,EDX

		CONVERT	EAX,EAX,SEGMENT_GARRAY
		ASSUME	EAX:PTR SEGMENT_STRUCT

		MOV	ECX,[EAX]._SEG_OS2_NUMBER
		MOV	EDX,[EAX]._SEG_OS2_FLAGS

		MOV	FIX2_OS2_TNUMBER,ECX
		MOV	FIX2_OS2_TFLAGS,EDX

		MOV	AL,[EAX]._SEG_TYPE
		OR	EDX,EDX

		RET

TARG_SEGMOD_NORMAL	ENDP


TARG_SEGMOD_CV	PROC	NEAR
		;
		;EAX IS SEGMOD GINDEX
		;
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		PUSH	EDI
		MOV	EDI,[EAX]._SM_BASE_SEG_GINDEX
		CONVERT	EDI,EDI,SEGMENT_GARRAY
		ASSUME	EDI:PTR SEGMENT_STRUCT

		PUSH	EBX
		MOV	ECX,[EAX]._SM_START		;OFFSET FROM FRAME

		MOV	EBX,[EDI]._SEG_CV_NUMBER
		MOV	EDX,[EDI]._SEG_OFFSET

		MOV	FIX2_TFRAME_SEG,EBX
		SUB	ECX,EDX				;NEED JUST OFFSET FROM SEGMENT_GINDEX

if	fg_cvpack
		MOV	DL,FIX2_SEG_TYPE
		GETT	BL,CVPACK_FLAG

		AND	DL,MASK SEG_CV_SYMBOLS1
		MOV	BH,[EAX]._SM_FLAGS

		AND	DL,BL
		JZ	L1$

		AND	BH,MASK SEG_CLASS_IS_CODE
		JZ	L1$
		;
		;CODESEG, $$SYMBOLS, CVPACK.  IF IT AIN'T MY CODESEG, ADD 8000H TO NUMBER
		;
		PUSH	ECX
		CALL	GET_SM_MODULE		;EAX IS SEGMOD PHYSICAL, RETURN EAX IS PARENT MODULE GINDEX

		POP	ECX
		MOV	EBX,CURNMOD_GINDEX

		CMP	EBX,EAX
		JZ	L1$

		OR	FIX2_TFRAME_SEG,8000H
L1$:
endif
		MOV	EDX,FIX2_TOFFSET
		MOV	AL,[EDI]._SEG_TYPE

		ADD	ECX,EDX
		XOR	EBX,EBX			;CLEAR CARRY

		MOV	FIX2_OS2_TFLAGS,EBX
		MOV	FIX2_TOFFSET,ECX

		POPM	EBX,EDI

		RET

TARG_SEGMOD_CV	ENDP


if	fg_pe

TARG_SEGMOD_CV32	PROC	NEAR
		;
		;EAX IS SEGMOD GINDEX
		;
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		PUSH	EDI
		MOV	EDI,[EAX]._SM_BASE_SEG_GINDEX
		CONVERT	EDI,EDI,SEGMENT_GARRAY
		ASSUME	EDI:PTR SEGMENT_STRUCT

		PUSH	EBX
		MOV	ECX,[EAX]._SM_START		;OFFSET FROM FRAME

		MOV	EDX,[EDI]._SEG_PEOBJECT_NUMBER
		MOV	FIX2_TFRAME_SEG,EDX		;FRAME IS SEGMENT_GINDEX
if	fg_cvpack
		MOV	DL,FIX2_SEG_TYPE
		GETT	BL,CVPACK_FLAG

		AND	DL,MASK SEG_CV_SYMBOLS1
		MOV	BH,[EAX]._SM_FLAGS

		AND	DL,BL
		JZ	L1$

		AND	BH,MASK SEG_CLASS_IS_CODE
		JZ	L1$
		;
		;CODESEG, $$SYMBOLS, CVPACK.  IF IT AIN'T MY CODESEG, ADD 8000H TO NUMBER
		;
		PUSH	ECX
		CALL	GET_SM_MODULE

		MOV	EBX,CURNMOD_GINDEX
		POP	ECX

		CMP	EBX,EAX
		JZ	L1$

		OR	FIX2_TFRAME_SEG,8000H
L1$:
endif
		MOV	EDX,[EDI]._SEG_PEOBJECT_GINDEX
		MOV	EAX,PE_BASE

		TEST	EDX,EDX
		JZ	L9$

		CONVERT	EDX,EDX,PE_OBJECT_GARRAY
		ASSUME	EDX:PTR PE_OBJECT_STRUCT

		SUB	ECX,EAX
		MOV	EAX,[EDX]._PEOBJECT_RVA		;NEED JUST OFFSET FROM SEGMENT_GINDEX

		MOV	EDX,FIX2_TOFFSET
		SUB	ECX,EAX

		ADD	ECX,EDX
		MOV	AL,[EDI]._SEG_TYPE

		MOV	FIX2_TOFFSET,ECX
		OR	AH,AH				;CLEAR CARRY
L9$:

		POPM	EBX,EDI

		MOV	FIX2_OS2_TFLAGS,0

		RET

TARG_SEGMOD_CV32	ENDP

endif

TARG_GROUP_NORMAL	PROC	NEAR
		;
		;EAX IS GROUP GINDEX
		;
		CONVERT	EAX,EAX,GROUP_GARRAY
		ASSUME	EAX:PTR GROUP_STRUCT

		MOV	EDX,[EAX]._G_FIRST_SEG_GINDEX
		MOV	ECX,[EAX]._G_OFFSET

		MOV	FIX2_SEG_GINDEX,EDX
		MOV	EDX,FIX2_TOFFSET

		ADD	EDX,ECX
		MOV	ECX,[EAX]._G_OS2_NUMBER

		MOV	FIX2_TOFFSET,EDX
		MOV	EDX,[EAX]._G_OS2_FLAGS

		MOV	FIX2_OS2_TNUMBER,ECX
		MOV	FIX2_OS2_TFLAGS,EDX

		MOV	AL,[EAX]._G_TYPE		;FOR CHECKING RELOC VS ASEG
		OR	ECX,ECX				;CLEAR CARRY

		RET

TARG_GROUP_NORMAL	ENDP


TARG_GROUP_CV	PROC	NEAR
		;
		;EAX IS GROUP GINDEX
		;

		CONVERT	EAX,EAX,GROUP_GARRAY		;CODEVIEW DOESN'T SUPPORT GROUP STUFF...
		ASSUME	EAX:PTR GROUP_STRUCT

		MOV	ECX,[EAX]._G_FIRST_SEG_GINDEX
		MOV	AL,[EAX]._G_TYPE

		TEST	ECX,ECX
		JZ	L1$

		CONVERT	ECX,ECX,SEGMENT_GARRAY
		ASSUME	ECX:PTR SEGMENT_STRUCT
		MOV	ECX,[ECX]._SEG_CV_NUMBER
L1$:
		XOR	EDX,EDX

		MOV	FIX2_TFRAME_SEG,ECX
		MOV	FIX2_OS2_TFLAGS,EDX

		RET

TARG_GROUP_CV	ENDP


if	fg_pe

TARG_GROUP_CV32	PROC	NEAR
		;
		;EAX IS GROUP GINDEX
		;
		CONVERT	EAX,EAX,GROUP_GARRAY
		ASSUME	EAX:PTR GROUP_STRUCT

		MOV	ECX,[EAX]._G_FIRST_SEG_GINDEX
		MOV	AL,[EAX]._G_TYPE		;FOR CHECKING RELOC VS ASEG

		TEST	ECX,ECX
		JZ	L1$

		CONVERT	ECX,ECX,SEGMENT_GARRAY
		ASSUME	ECX:PTR SEGMENT_STRUCT

		MOV	ECX,[ECX]._SEG_PEOBJECT_NUMBER
L1$:
		XOR	EDX,EDX				;CLEAR CARRY

		MOV	FIX2_OS2_TFLAGS,EDX
		MOV	FIX2_TFRAME_SEG,ECX

		RET

TARG_GROUP_CV32	ENDP

endif

TARG_ASEG_NORMAL	PROC	NEAR
TARG_ASEG_CV::
		;
		;EAX IS PARAGRAPH - SELECTOR FOR SEGM MODE
		;
if	fg_segm
		GETT	CL,OUTPUT_SEGMENTED
		XOR	EDX,EDX

		TEST	CL,CL
		JNZ	L5$
endif
		SHL	EAX,4
		MOV	ECX,FIX2_TOFFSET

		ADD	ECX,EAX
		MOV	FIX2_OS2_TNUMBER,EAX

		MOV	FIX2_TOFFSET,ECX
		MOV	FIX2_OS2_TFLAGS,EDX

		MOV	AL,MASK SEG_ASEG
		OR	ECX,ECX				;CLEAR CARRY

		MOV	FIX2_SEG_GINDEX,EDX

		RET

if	fg_segm
L5$:
		MOV	FIX2_OS2_TNUMBER,EAX
		MOV	FIX2_OS2_TFLAGS,EDX

		MOV	AL,MASK SEG_ASEG
		OR	ECX,ECX
		RET
endif

TARG_ASEG_NORMAL	ENDP


TARG_EXTERNAL_CV	PROC	NEAR
		;
		;EAX IS SYMBOL GINDEX
		;
		CONVERT	EAX,EAX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT

		XOR	EDX,EDX
		MOV	CL,[EAX]._S_NSYM_TYPE

		MOV	EBX,[EAX]._S_SEG_GINDEX
		MOV	FIX2_OS2_TFLAGS,EDX

		TEST	EBX,EBX
		JZ	L1$

		CONVERT	EBX,EBX,SEGMENT_GARRAY
		ASSUME	EBX:PTR SEGMENT_STRUCT

		MOV	EDX,[EBX]._SEG_CV_NUMBER
		MOV	EDI,[EAX]._S_OFFSET	;TOTAL OFFSET
L1$:
		MOV	FIX2_TFRAME_SEG,EDX

		CMP	CL,NSYM_RELOC		;NORMALLY RELOC
		JZ	L2$
		CMP	CL,NSYM_CONST
		JZ	L3$
		CMP	CL,NSYM_ASEG
		JNZ	L8$
L2$:
if	fg_cvpack
		MOV	EAX,[EAX]._S_DEFINING_MOD
		MOV	EDX,CURNMOD_GINDEX

		CMP	EDX,EAX
		JZ	L25$

		GETT	AL,CVPACK_FLAG
		MOV	DL,FIX2_SEG_TYPE

		OR	AL,AL
		JZ	L25$

		AND	DL,MASK SEG_CV_SYMBOLS1
		JZ	L25$

		OR	FIX2_TFRAME_SEG,8000H
L25$:

endif
		;
		;USE NORMAL ADDRESS
		;
		SUB	EDI,[EBX]._SEG_OFFSET		;NEED OFFSET FROM GINDEX
L3$:
		AND	ECX,NSYM_ANDER
		MOV	EAX,FIX2_TOFFSET

		SHR	ECX,1
		ADD	EAX,EDI

		MOV	FIX2_TOFFSET,EAX

		MOV	AL,FIX2_EXT_TYPE_XLAT[ECX]

		RET

L8$:
		OR	[EAX]._S_REF_FLAGS,MASK S_REFERENCED

		STC

		RET

TARG_EXTERNAL_CV	ENDP


if	fg_pe

TARG_EXTERNAL_CV32	PROC	NEAR
		;
		;EAX IS SYMBOL GINDEX
		;
		CONVERT	EAX,EAX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT

		XOR	EDX,EDX
		MOV	CL,[EAX]._S_NSYM_TYPE

		MOV	EBX,[EAX]._S_SEG_GINDEX
		MOV	FIX2_OS2_TFLAGS,EDX

		TEST	EBX,EBX
		JZ	L1$

		CONVERT	EBX,EBX,SEGMENT_GARRAY
		ASSUME	EBX:PTR SEGMENT_STRUCT

		MOV	EDX,[EBX]._SEG_PEOBJECT_NUMBER
		MOV	EBX,[EBX]._SEG_PEOBJECT_GINDEX
L1$:
		MOV	EDI,[EAX]._S_OFFSET
		MOV	FIX2_TFRAME_SEG,EDX

		CMP	CL,NSYM_RELOC		;NORMALLY RELOC
		JZ	L2$

		CMP	CL,NSYM_CONST
		JZ	L3$

		CMP	CL,NSYM_ASEG
		JNZ	L8$
L2$:
if	fg_cvpack
		MOV	EAX,[EAX]._S_DEFINING_MOD
		MOV	EDX,CURNMOD_GINDEX

		CMP	EDX,EAX
		JZ	L25$

		GETT	AL,CVPACK_FLAG
		MOV	DL,FIX2_SEG_TYPE

		OR	AL,AL
		JZ	L25$

		AND	DL,MASK SEG_CV_SYMBOLS1
		JZ	L25$

		OR	FIX2_TFRAME_SEG,8000H
L25$:

endif
		;
		;USE NORMAL ADDRESS
		;
		CONVERT	EBX,EBX,PE_OBJECT_GARRAY
		ASSUME	EBX:PTR PE_OBJECT_STRUCT

		MOV	EDX,[EBX]._PEOBJECT_RVA
		MOV	EBX,PE_BASE

		SUB	EDI,EDX

		SUB	EDI,EBX		

L3$:
		AND	ECX,NSYM_ANDER
		MOV	EAX,FIX2_TOFFSET

		SHR	ECX,1
		ADD	EAX,EDI

		MOV	FIX2_TOFFSET,EAX

		MOV	AL,FIX2_EXT_TYPE_XLAT[ECX]

		RET

L8$:
		OR	[EAX]._S_REF_FLAGS,MASK S_REFERENCED

		STC

		RET

TARG_EXTERNAL_CV32	ENDP

endif


TARG_EXTERNAL_NORMAL	PROC	NEAR
		;
		;EAX IS SYMBOL GINDEX
		;
		CONVERT	EAX,EAX,SYMBOL_GARRAY

		MOV	ECX,DPTR [EAX]._S_NSYM_TYPE
		GETT	DL,OUTPUT_SEGMENTED

if	fg_segm OR fg_pe
		CMP	CL,NSYM_IMPORT
		JZ	L5$			;IMPORTED
endif

		CMP	CL,NSYM_RELOC
		JZ	L2$

if	fg_segm
		AND	CH,MASK S_FLOAT_SYM
		JNZ	L6$
L61$:
endif
		CMP	CL,NSYM_CONST
		JZ	L39$

		CMP	CL,NSYM_ASEG
		JZ	L39$

		OR	[EAX]._S_REF_FLAGS,MASK S_REFERENCED

		MOV	FIX2_OS2_TFLAGS,0

		STC

		RET

L2$:
L39$:
		MOV	EDX,[EAX]._S_SEG_GINDEX
		MOV	EBX,[EAX]._S_OFFSET	;TOTAL OFFSET FROM SEGMENT

		MOV	FIX2_SEG_GINDEX,EDX
		MOV	EDX,FIX2_TOFFSET

		AND	ECX,NSYM_ANDER
		ADD	EDX,EBX

		SHR	ECX,1
		MOV	EBX,[EAX]._S_OS2_NUMBER
	
		MOV	FIX2_TOFFSET,EDX
		MOV	EDI,[EAX]._S_OS2_FLAGS

if	fg_pe OR fg_segm
		GETT	AL,OUTPUT_PE
		GETT	DL,OUTPUT_SEGMENTED

		OR	AL,DL
		JNZ	L41$
endif

		SHL	EBX,4		;THIS ZEROS DX FIRST...
L41$:
		MOV	FIX2_OS2_TFLAGS,EDI
		MOV	FIX2_OS2_TNUMBER,EBX

		OR	EBX,EBX
		MOV	AL,FIX2_EXT_TYPE_XLAT[ECX]
		RET

if	fg_segm OR fg_pe

L5$:
if	fg_pe
		GETT	DH,OUTPUT_PE
		MOV	CL,NSYM_RELOC

		TEST	DH,DH
		JNZ	L2$
endif
		;
		;TARGET IS AN IMPORTED SYMBOL...
		;
		XOR	EDX,EDX
		AND	CH,MASK S_IMP_ORDINAL

		MOV	ECX,[EAX]._S_IMP_NOFFSET	;NAME OFFSET
		JZ	L53$

		INC	EDX
		MOV	ECX,[EAX]._S_IMP_ORDINAL
L53$:
		MOV	EBX,[EAX]._S_IMP_MODULE		;MODULE #
		MOV	FIX2_IMP_OFFSET,ECX

		MOV	FIX2_IMP_MODULE,EBX
		MOV	EBX,MASK SR_1		;MARK IT IMPORTED (AVAILABLE FLAG...)

		MOV	FIX2_IMP_FLAGS,EDX
		MOV	FIX2_OS2_TFLAGS,EBX

		MOV	AL,MASK SEG_RELOC
		OR	ECX,ECX			;CLEAR CARRY

		RET

endif

if	fg_segm

L6$:

if	fg_norm_exe
		TEST	DL,DL		;OUTPUT_SEGMENTED
		JZ	L61$
endif
		MOV	AL,BPTR [EAX]._S_FLOAT_TYPE
if	fg_winpack
		GETT	DL,WINPACK_SELECTED
endif
		AND	EAX,7
		JZ	L7$			;JUST USE ZEROS
if	fg_winpack
		CMP	AL,6
		JNZ	L65$
		TEST	DL,DL
		JNZ	L67$
L65$:
endif
		XOR	ECX,ECX
		MOV	FIX2_IMP_OFFSET,EAX	;BASE.LW OR FIX2_IMP_OFFSET

		MOV	FIX2_IMP_MODULE,ECX	;BASE.HW OR FIX2_IMP_MODULE
		MOV	EAX,MASK SR_1		;AVAILABLE FLAG...

		MOV	FIX2_IMP_FLAGS,ECX	;OS2_NUMBER (IMPORT_FLAGS)
		MOV	FIX2_OS2_TFLAGS,EAX	;MARK IT IMPORTED FOR SPECIAL TREATMENT

		MOV	AL,MASK SEG_CONST

		RET

if	fg_winpack
L67$:
		MOV	ECX,0A23DH
		MOV	FIX2_IMP_OFFSET,EAX	;BASE.LW OR FIX2_IMP_OFFSET

		MOV	FIX2_TOFFSET,ECX
		XOR	EAX,EAX

		JMP	L8$

endif
L7$:
		MOV	FIX2_IMP_OFFSET,EAX	;BASE.LW OR FIX2_IMP_OFFSET
L8$:
		MOV	FIX2_OS2_TNUMBER,EAX	;IGNORE THESE AS CONSTANT ZERO
		MOV	FIX2_OS2_TFLAGS,EAX
		MOV	AL,MASK SEG_CONST
		RET

endif

TARG_EXTERNAL_NORMAL	ENDP


FRAME_LOC	PROC	NEAR
		;
		;
		;
		MOV	EAX,FIX2_LDATA_SEGMENT_GINDEX

FRAME_LOC	ENDP


FRAME_SEGMENT	PROC	NEAR
		;
		;EAX IS GINDEX OF A SEGMENT
		;
		CONVERT	EAX,EAX,SEGMENT_GARRAY
		ASSUME	EAX:PTR SEGMENT_STRUCT

		MOV	ECX,[EAX]._SEG_OS2_NUMBER
;		MOV	EDX,[EAX]._SEG_OS2_FLAGS

		MOV	AL,[EAX]._SEG_TYPE
		OR	EBX,EBX			;CLEAR CARRY

		RET

FRAME_SEGMENT	ENDP


FRAME_GROUP	PROC	NEAR
		;
		;EAX IS GINDEX OF GROUP
		;
		CONVERT	EAX,EAX,GROUP_GARRAY
		ASSUME	EAX:PTR GROUP_STRUCT

		MOV	ECX,[EAX]._G_OS2_NUMBER
;		MOV	EDX,[EAX]._G_OS2_FLAGS

		MOV	AL,[EAX]._G_TYPE
		OR	EBX,EBX			;CLEAR CARRY

		RET

FRAME_GROUP	ENDP


FRAME_ABSOLUTE	PROC	NEAR
		;
		;
		;
		MOV	ECX,EAX
if	fg_segm
		GETT	AL,OUTPUT_SEGMENTED

		OR	AL,AL
		JNZ	L5$
endif
		SHL	ECX,4
L5$:

		MOV	AL,MASK SEG_ASEG
		OR	EDX,EDX			;CLEAR CARRY

		RET

FRAME_ABSOLUTE	ENDP


FRAME_EXTERNAL	PROC	NEAR
		;
		;THIS SHOULD BE SUPER-RARE?
		;
		CONVERT	EAX,EAX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT

		MOV	EDX,DPTR [EAX]._S_NSYM_TYPE
if	fg_segm
		CMP	DL,NSYM_IMPORT
		JZ	L5$			;IMPORTED, USE ASEG ZERO

		AND	DH,MASK S_FLOAT_SYM
		JNZ	L5$
L61$:
endif
		CMP	DL,NSYM_RELOC
		JZ	L2$

		CMP	DL,NSYM_CONST
		JZ	L39$

		CMP	DL,NSYM_ASEG
		JZ	L39$

		OR	[EAX]._S_REF_FLAGS,MASK S_REFERENCED

		STC

		RET

L5$:
		XOR	ECX,ECX
		MOV	AL,MASK SEG_CONST+MASK SEG_ASEG

		RET

L2$:
L39$:
		AND	EDX,NSYM_ANDER
		MOV	ECX,[EAX]._S_OS2_NUMBER

		SHR	EDX,1
if	fg_segm
		GETT	AL,OUTPUT_SEGMENTED

		OR	AL,AL
		JNZ	L41$
endif
		SHL	ECX,4
L41$:

		MOV	AL,FIX2_EXT_TYPE_XLAT[EDX]
		OR	ECX,ECX

		RET

FRAME_EXTERNAL	ENDP


FRAME_TARG	PROC	NEAR
		;
		;
		;
		MOV	AL,FIX2_TTYPE
		MOV	ECX,FIX2_OS2_TNUMBER

;		MOV	EDX,FIX2_OS2_TFLAGS
		OR	EAX,EAX			;CLEAR CARRY

		RET

FRAME_TARG	ENDP

if	fg_segm

DO_IMPORT	PROC	NEAR
		;
		;TARGET STUFF IS AN IMPORT SYMBOL, CH IS FLAGS, CL IS FIXTYPE
		;
		;IF ADDITIVE, INSERT A NEW REFERENCE, ELSE TRY LINK LIST
		;
		;MUST IT BE ADDITIVE?
		;
		MOV	EAX,FIX2_IMP_FLAGS
		MOV	DL,2

		TEST	AL,AL			;ZERO IS IMPORT-BY-NAME
		JZ	L1$

		DEC	EDX			;MUST BE IMPORT BY NUMBER
L1$:
		ADD	EDI,EBX
		OR	CH,DL

		MOV	EAX,FIX2_LDATA_LOC
		MOV	EDX,FIX2_IMP_MODULE

		ADD	EAX,EBX		;TARGET LOGICAL ADDRESS
		MOV	EBX,FIX2_IMP_OFFSET

		;ES:DI IS PHYS_PTR
		;AX IS OFFSET IN SEGMENT
		;BX IS _RL_IMP_OFFSET
		;CL IS FIXUPP TYPE
		;CH IS FIXUPP FLAGS
		;DX IS _RL_IMP_MODULE
		;
		JMP	RELOC_INSTALL	;DO RELOCATION

DO_IMPORT	ENDP

endif

if	fg_segm

DO_INTERNAL	PROC	NEAR
		;
		;TARGET STUFF IS AN INTERNAL, CH IS FLAGS, CL IS FIXTYPE
		;
		ADD	EDI,EBX
		XOR	EDX,EDX

		XCHG	DX,WPTR [EDI]

		ADD	EAX,EDX
		MOV	EDX,FIX2_LDATA_LOC

		ADD	EBX,EDX
		MOV	EDX,EAX

		MOV	EAX,EBX
		MOV	EBX,EDX

		MOV	EDX,FIX2_OS2_TNUMBER

		;ES:DI IS PHYS_PTR
		;AX IS OFFSET IN SEGMENT
		;BX IS TARGET SEGMENT OFFSET
		;CL IS FIXUPP TYPE
		;CH IS FIXUPP FLAGS
		;DX IS TARGET SEGMENT #
		;
		JMP	RELOC_INSTALL	;DO RELOCATION

DO_INTERNAL	ENDP

endif

RELOCATION_CHECK	PROC
		;
		;EAX IS ADDRESS
		;
		PUSH	EBX
		MOV	DL,FIX2_LD_TYPE

		AND	DL,MASK BIT_LI
		JNZ	L9$

		MOV	ECX,DPTR FIX2_LD_LENGTH
		POP	EBX

		AND	ECX,0FFFFH

REL_CHK_LIDATA	LABEL	PROC
		;
		;EAX IS STARTING ADDRESS, ECX IS NUMBER OF BYTES
		;
		;
		;QUICK CHECK WOULD BE IF BX:AX IS ABOVE RELOC_HIGH_WATER
		;
		PUSH	EBX

		MOV	EDX,FIX2_STACK_DELTA
		MOV	EBX,FIX2_SM_START

		ADD	EAX,EDX
		MOV	EDX,RELOC_HIGH_WATER

		SUB	EAX,EBX
		MOV	EBX,FIRST_RELOC_GINDEX

		CMP	EDX,EAX
		JBE	L9$
		;
		;SEE IF THIS OVERLAPS ANY RELOCATION RECORDS
		;
		TEST	EBX,EBX
		JZ	L9$		;HOME FREE, NO RELOCS THIS SEGMENT
		;
		;MORE DIFFICULT, NEED TO CHECK BITMAP...
		;AX IS FIRST BIT TO CHECK, FIX2_LD_LENGTH IS PROBABLY #
		;OF BITS TO CHECK
		;
		POP	EBX

SPECIAL_RELOC_CHECK	LABEL	PROC
		;
		;AX IS FIRST BIT TO CHECK, CX IS NUMBER OF BITS
		;
		PUSHM	EBX,EDI

		PUSH	EAX
		MOV	EBX,EAX

		SHR	EAX,3
		MOV	EDI,RELOC_BITS

		PUSH	ECX
		ADD	EDI,EAX
		;
		;DI IS BIT #
		;CX IS # OF BITS
		;
		;GET TO A BYTE BOUNDARY
		;
		AND	EBX,7
		JZ	L55$		;ALREADY A BYTE BOUNDARY

		MOV	EAX,EBX
		MOV	EBX,ECX

		MOV	ECX,EAX
		MOV	AL,[EDI]

		SHR	AL,CL

		SUB	CL,8
		INC	EDI

		NEG	CL		;# OF BITS TO CHECK IN THIS BYTE
L51$:
		DEC	EBX
		JS	L8$

		SHR	AL,1
		JC	L7$

		DEC	ECX
		JNZ	L51$

		MOV	ECX,EBX
L55$:
		MOV	EDX,ECX
		XOR	EAX,EAX

		SHR	ECX,3		;CX IS # OF BYTES TO CHECK
		JZ	L551$

		REPE	SCASB
L551$:
		MOV	AL,[EDI]
		JNZ	L7$

		OR	AL,AL
		JZ	L8$

		AND	EDX,7		;# OF BITS TO CHECK
		JZ	L8$
L56$:
		SHR	AL,1
		JC	L7$

		DEC	EDX
		JNZ	L56$
L8$:
		POPM	ECX,EAX

		POP	EDI
L9$:
		POP	EBX

		RET

L7$:
		;
		;PRESERVE DS:SI
		;
		;CONFLICT WITH PREVIOUS RELOCATIONS...
		;
		MOV	ECX,FIX2_LDATA_SEGMENT_GINDEX
		MOV	AL,RELOC_CONFLICT_ERR
		CONVERT	ECX,ECX,SEGMENT_GARRAY
		ASSUME	ECX:PTR SEGMENT_STRUCT

		ADD	ECX,SEGMENT_STRUCT._SEG_TEXT
		CALL	ERR_ASCIZ_RET
		JMP	L8$

RELOCATION_CHECK	ENDP


DO_FARCALL_FIXUPPS	PROC
		;
		;THIS IS LIST OF POSSIBLE FARCALLTRANSLATIONS
		;
		XOR	EAX,EAX

		MOV	FIX2_LDATA_BASE,EAX
		MOV	LDATA_SEGMOD_GINDEX,EAX

		MOV	FIX2_LDATA_SEGMENT_GINDEX,EAX
		MOV	FIXUPP_COUNT,EAX

		CMP	FIRST_FARCALL,EAX
		JZ	L91$
if	debug
		MOV	EAX,OFF FARCALL_MSG
		CALL	SAY_VERBOSE
endif
		;
		MOV	ESI,FIRST_FARCALL

L1$:
		TEST	ESI,ESI
		JZ	L9$
L2$:
		MOV	EDI,OFF FIX2_FIXUPP_STUFF
		ASSUME	ESI:PTR FARCALL_HEADER_TYPE
		ASSUME	EDI:PTR FARCALL_HEADER_TYPE
		MOV	ECX,[ESI]._FC_NEXT_FARCALL

		MOV	EAX,[ESI]._FC_SEGMOD_GINDEX
		MOV	[EDI]._FC_NEXT_FARCALL,ECX

		MOV	[EDI]._FC_SEGMOD_GINDEX,EAX
		MOV	EAX,[ESI]._FC_LENGTH

		MOV	ECX,[ESI]._FC_BLOCK_BASE
		ADD	ESI,SIZEOF FARCALL_HEADER_TYPE

		MOV	[EDI]._FC_LENGTH,EAX
		MOV	[EDI]._FC_BLOCK_BASE,ECX

		ASSUME	ESI:NOTHING,EDI:NOTHING

		ADD	EAX,ESI
		MOV	FIX2_LDATA_BASE,ECX

		MOV	FIX2_FIXUPP_EOR,EAX
		;
		;SET UP SEGMENT, ETC
		;
		MOV	EAX,FIX2_FC_SEGMOD_GINDEX
		MOV	ECX,LDATA_SEGMOD_GINDEX

		CMP	ECX,EAX
		JNZ	L4$
L51$:
		CALL	DO_FF_1
L56$:
		MOV	ESI,FIX2_FH_NEXT_FIXUPP
		MOV	EAX,FIX2_LDATA_BASE

		TEST	ESI,ESI
		JZ	L8$

		ASSUME	ESI:PTR FARCALL_HEADER_TYPE
		MOV	ECX,[ESI]._FC_BLOCK_BASE

		CMP	EAX,ECX
		JZ	L2$

		TEST	EAX,EAX
		JZ	L1$

		CALL	RELEASE_BLOCK
		JMP	L1$

L8$:
		CALL	RELEASE_BLOCK

L9$:
if	debug

		MOV	EAX,OFF FARCALLFINI_MSG
		CALL	SAY_VERBOSE
endif
L91$:
		MOV	EAX,FIXUPP_COUNT
		MOV	ECX,FIRST_SECTION_GINDEX

		TEST	EAX,EAX
		JZ	L99$

		CONVERT	ECX,ECX,SECTION_GARRAY
		ASSUME	ECX:PTR SECTION_STRUCT

		SUB	[ECX]._SECT_RELOCS,EAX

L99$:
		RET

L4$:
		;
		;SEGMOD CHANGED
		;
		PUSH	ESI
		MOV	LDATA_SEGMOD_GINDEX,EAX

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		MOV	ESI,EAX
		ASSUME	ESI:PTR SEGMOD_STRUCT
		CALL	GET_SM_MODULE

		GETT	CL,ENTRIES_POSSIBLE
		MOV	CURNMOD_GINDEX,EAX

		OR	CL,CL
		JNZ	L45$
L44$:
		MOV	AL,[ESI]._SM_PLTYPE

		TEST	AL,MASK LEVEL_0_SECTION
		JZ	L55$
L45$:
		MOV	EAX,[ESI]._SM_BASE_SEG_GINDEX
		MOV	ECX,FIX2_LDATA_SEGMENT_GINDEX

		TEST	EAX,EAX			;SKIP IF FROM AN UNREFERENCED COMDAT...
		JZ	L55$

		CMP	ECX,EAX
		JZ	L52$
L5$:
		MOV	FIX2_LDATA_SEGMENT_GINDEX,EAX
		CONVERT	ESI,EAX,SEGMENT_GARRAY
		ASSUME	ESI:PTR SEGMENT_STRUCT

		MOV	EDI,OFF FIX2_SEGMENT_STUFF
		MOV	ECX,(SIZE SEGMENT_STRUCT+3)/4

		REP	MOVSD

		ASSUME	ESI:NOTHING

L52$:
if	fg_segm
		GETT	CL,ENTRIES_POSSIBLE
		POP	ESI

		GETT	DL,PROTMODE
		MOV	EAX,FIX2_SEG_OS2_FLAGS

		OR	CL,CL
		JZ	L51$
		;
		;HMM, THIS IS FOR PENTS
		;
		OR	DL,DL
		JZ	L51$
		;
		;IGNORE IF ITS A COMDAT THAT BECAME IOPL-NONCONFORMING-CODE
		;
		TEST	EAX,MASK SR_CONF+1
		JNZ	L51$
		TEST	EAX,1 SHL SR_DPL
		JZ	L51$

endif

L55$:
		XOR	EAX,EAX
		POP	ECX

		MOV	LDATA_SEGMOD_GINDEX,EAX
		JMP	L56$

DO_FARCALL_FIXUPPS	ENDP


DO_FF_1 	PROC	NEAR
		;
		;
		;
		MOV	EAX,[ESI]
		ADD	ESI,4

		AND	EAX,0FFFFH
		CALL	PARSE_FIXUPP2

		GETT	AL,ENTRIES_POSSIBLE
		JC	L8$
if	fg_segm
		OR	AL,AL
		JZ	L3$

		MOV	EAX,[ESI]
		ADD	ESI,4

		MOV	LATEST_PENT_GINDEX,EAX
L3$:

endif
		;
		;SO, GO AHEAD AND DO FIXUPP
		;
if	fg_segm
		GETT	AL,OUTPUT_SEGMENTED

		OR	AL,AL
		JZ	L5$

		MOV	EAX,FIX2_OS2_TNUMBER
		MOV	ECX,FIX2_SEG_OS2_NUMBER

		CMP	ECX,EAX
		JNZ	L7$
		JMP	L6$
endif

L5$:
		;
		;FRAME MUST MATCH FRAME OF LDATA_LOC
		;
		MOV	EAX,FIX2_SEG_FRAME
		MOV	EBX,FIX2_FFRAME

		CMP	EAX,EBX
		JNZ	L7$

		CMP	EAX,FIX2_TFRAME
		JNZ	L7$
L6$:
		INC	FIXUPP_COUNT
if	fg_segm
		MOV	EAX,LATEST_PENT_GINDEX

		TEST	EAX,EAX
		JZ	L7$

		CONVERT	EAX,EAX,PENT_GARRAY
		ASSUME	EAX:PTR PENT_STRUCT

		DEC	[EAX]._PENT_REF_COUNT

endif
L7$:
		CMP	FIX2_FIXUPP_EOR,ESI
		JA	DO_FF_1

		RET

L8$:
if	fg_segm
		OR	AL,AL
		JZ	L7$

		ADD	ESI,4
		JMP	L7$

endif

DO_FF_1 	ENDP


RELINK_DATA_BACKWARDS	PROC	NEAR
		;
		;RELINK THIS LIST IN OPPOSITE DIRECTION...
		;
		MOV	ESI,FIX2_SM_FIRST_DAT
		ASSUME	ESI:PTR LDATA_HEADER_TYPE

		XOR	EBX,EBX

		TEST	ESI,ESI
		JZ	L9$
L1$:
		MOV	EAX,[ESI]._LD_NEXT_LDATA
		MOV	[ESI]._LD_NEXT_LDATA,EBX

		MOV	EBX,ESI
		MOV	ESI,EAX

		TEST	EAX,EAX
		JNZ	L1$
L9$:
		MOV	FIX2_SM_FIRST_DAT,EBX
		RET

		ASSUME	ESI:NOTHING

RELINK_DATA_BACKWARDS	ENDP


if	any_overlays

SI_FIXER	PROC	NEAR
		;
		;
		;
		CMP	SI,PAGE_SIZE
		JAE	1$
		RET

1$:
		SUB	SI,PAGE_SIZE-BLOCK_BASE
		MOV	DS,DX
		SYM_CONV_DS
		RET

SI_FIXER	ENDP

endif


HANDLE_START_ADDRESS	PROC	NEAR
		;
		;HANDLE START ADDRESS FIXUPP IF THERE, WARN IF MISSING...
		;
		MOV	ESI,MODEND_ADDRESS
		OR	ESI,ENTRYPOINT_GINDEX
if	debug
		JZ	L0$
		MOV	EAX,OFF START_MSG
		CALL	SAY_VERBOSE
L0$:
		TEST	ESI,ESI
endif
		JZ	L5$

		SETT	DOING_START_ADDRESS

		MOV	EAX,MODEND_OWNER_GINDEX
		XOR	ECX,ECX

		MOV	CURNMOD_GINDEX,EAX
		MOV	FIX2_FIXUPP_BASE,ECX	;OR RELEASED

if	fg_norm_exe
		MOV	FIX2_LDATA_PTR,OFF EXEHEADER._EXE_REG_IP
endif

		MOV	EAX,ENTRYPOINT_GINDEX

		OR	EAX,EAX
		JZ	L1$

		MOV	FIX2_TINDEX,EAX
		XOR	ECX,ECX

		MOV	FIX2_OFFSET,ECX
		MOV	FIX2_TOFFSET,ECX

		MOV	FIX2_TT,2		;SYMBOL
		MOV	FIX2_FF,5		;FRAME TARG
		MOV	FIX2_LOC,13H		;16:16

		CALL	TARG_EXTERNAL_NORMAL

		MOV	FIX2_TTYPE,AL
		CALL	FRAME_TARG

		MOV	FIX2_FTYPE,AL
		MOV	FIX2_OS2_FNUMBER,ECX

		MOV	ESI,OFF TEMP_DATA_RECORD

		MOV	FIX2_FIXUPP_EOR,ESI		;FAKE END OF RECORD
		JMP	L14$

L1$:
		MOV	ESI,MODEND_ADDRESS

		MOV	EAX,[ESI]
		ADD	ESI,4

		ADD	EAX,ESI

		MOV	FIX2_FIXUPP_EOR,EAX
		CALL	DOF_PRELIM
		;
		;
L14$:
		MOV	AL,FIX2_TTYPE

		OR	AL,FIX2_FTYPE

		TEST	AL,MASK SEG_ASEG
		JZ	L15$
if	fg_rom
		BITT	OUTPUT_ABS
		JNZ	L15$
endif
		MOV	AL,START_ERR
		CALL	ERR_RET
L15$:
		MOV	FIX2_TTYPE,MASK SEG_ASEG	;NO RELOCATION...
		MOV	FIX2_FTYPE,MASK SEG_ASEG

		BITT	SYMBOL_UNDEFINED
		JZ	L2$
		JMP	L8$

L5$:
		;
		;DON'T COMPLAIN IF .DLL
		;
if	fg_segm OR fg_pe
		TEST	FLAG_0C,MASK APPTYPE
		JNZ	L52$
endif
		MOV	AL,NO_START_ERR
		CALL	WARN_RET
L52$:
		JMP	L9$

L2$:
if	fg_pe
		BITT	OUTPUT_PE
		JZ	L29$
		TEST	FIX2_OS2_TFLAGS,MASK SR_1
		JNZ	START_IMPORT
		MOV	EAX,FIX2_TOFFSET
		SUB	EAX,PE_BASE
		MOV	PEXEHEADER._PEXE_ENTRY_RVA,EAX
		JMP	L8$

L29$:
endif

if	fg_segm
L3$:
		BITT	OUTPUT_SEGMENTED
		JZ	L39$
		MOV	EAX,FIX2_OS2_TNUMBER	;TARGET SEGMENT MUST EQUAL
		CMP	FIX2_OS2_FNUMBER,EAX	;FRAME SEGMENT
		JNZ	L31$
		MOV	WPTR NEXEHEADER._NEXE_CSIP+2,AX

		TEST	FIX2_OS2_TFLAGS,MASK SR_1
		JNZ	START_IMPORT
		MOV	EAX,FIX2_TOFFSET
		MOV	WPTR NEXEHEADER._NEXE_CSIP,AX
		JMP	L8$

L31$:
		MOV	AL,START_CANT_REACH_ERR
L33$:
		CALL	ERR_RET
		JMP	L8$

START_IMPORT:
		MOV	AL,START_IMPORT_ERR
		JMP	L33$

L39$:
endif

if	fg_norm_exe

L4$:
		BITT	FARCALLTRANSLATION_FLAG
		JZ	L41$
		RESS	FARCALLTRANSLATION_FLAG
		CALL	DOFIXUPPS_MODEND
		SETT	FARCALLTRANSLATION_FLAG
		JMP	L49$

L41$:
		CALL	DOFIXUPPS_MODEND
L49$:
endif

L8$:
		XOR	EAX,EAX
		MOV	FIX2_LDATA_PTR,EAX
		MOV	EAX,DPTR EXEHEADER._EXE_REG_IP
		MOV	WM_START_ADDR,EAX

L9$:
		RESS	DOING_START_ADDRESS
		RET

HANDLE_START_ADDRESS	ENDP


if	fg_segm

RC_STARTER	PROC	NEAR
		;
		;
		;
		GETT	AL,OUTPUT_SEGMENTED
		MOV	EDX,SEGMENT_COUNT

		TEST	AL,AL
		JZ	L9$

		TEST	EDX,EDX
		JZ	L9$

		MOVZX	EAX,WPTR NEXEHEADER._NEXE_CSIP+2

		MOV	ESI,SEGMENT_TABLE_PTR
		MOV	EDI,MASK SR_PRELOAD

		ADD	ESI,SIZEOF SEGTBL_STRUCT+SEGTBL_STRUCT._SEGTBL_FLAGS		;OFFSET TO FLAGS

		CONV_EAX_SEGTBL_ECX

		OR	[ECX]._SEGTBL_FLAGS,EDI			;MARK START SEGMENT AS PRELOAD

		BITT	RC_REORDER
		JZ	L9$
		SETT	RC_PRELOADS
		BITT	RC_REORDER_SEGS
		JZ	L5$
L0$:
		MOV	EBX,MASK SR_DISCARD+MASK SR_MOVABLE
L1$:
		MOV	EAX,[ESI]
		ADD	ESI,SIZEOF SEGTBL_STRUCT

		MOV	ECX,EAX
		XOR	EAX,EBX

		TEST	EAX,EBX
		JZ	L2$

		OR	ECX,EDI
		MOV	[ESI - SIZEOF SEGTBL_STRUCT],ECX
L2$:
		DEC	EDX
		JNZ	L1$
L9$:
		RET

L5$:
if	fg_winpack
		BITT	WINPACK_SELECTED
		JNZ	L0$
endif
		;
		;MARK NOTHING PRELOADED
		;
		MOV	EDI,NOT MASK SR_PRELOAD
L6$:
		AND	[ESI],EDI
		ADD	ESI,SIZEOF SEGTBL_STRUCT

		DEC	EDX
		JNZ	L6$

		RET

RC_STARTER	ENDP

endif


SELECT_CV4_OUTPUT	PROC
		;
		;
		;
		MOV	LOC_10,OFF LOC_10_PROT
		MOV	LOC_CALLTBL_PTR,OFF LOC_CALLTBL_PROT
		RET

SELECT_CV4_OUTPUT	ENDP


		.CONST

		ALIGN	4

FIX2_TARG_TABLE_CV LABEL	DWORD

		DD	TARG_SEGMOD_CV
		DD	TARG_GROUP_CV
		DD	TARG_EXTERNAL_CV
		DD	TARG_ASEG_CV


FIX2_TARG_TABLE_NORMAL	LABEL	DWORD

		DD	TARG_SEGMOD_NORMAL
		DD	TARG_GROUP_NORMAL
		DD	TARG_EXTERNAL_NORMAL
		DD	TARG_ASEG_NORMAL


if	fg_pe

FIX2_TARG_TABLE_PE	LABEL	DWORD

		DD	TARG_SEGMOD_NORMAL
		DD	TARG_GROUP_NORMAL
		DD	TARG_EXTERNAL_NORMAL
		DD	TARG_ASEG_NORMAL


		PUBLIC	FIX2_TARG_TABLE_CV32

FIX2_TARG_TABLE_CV32 LABEL	DWORD

		DD	TARG_SEGMOD_CV32
		DD	TARG_GROUP_CV32
		DD	TARG_EXTERNAL_CV32
		DD	TARG_ASEG_CV

endif


FIX2_FRAME_TABLE	LABEL	DWORD

		DD	FRAME_SEGMENT
		DD	FRAME_GROUP
		DD	FRAME_EXTERNAL
		DD	FRAME_ABSOLUTE
		DD	FRAME_LOC
		DD	FRAME_TARG

;LOC_CALLTBL	LABEL	WORD


if	fg_prot

		ALIGN	4

LOC_CALLTBL_PROT	LABEL	DWORD
		;
		;16-BIT SELF-RELATIVE
		;
		DD	LOC_0_PROT
		DD	LOC_1_PROT
		REPT	6
		DD	BAD_MYLOC
		ENDM
		;32-BIT SELF-RELATIVE
		DD	BAD_MYLOC
		DD	LOC_32SELF_PROT
		REPT	6
		DD	BAD_MYLOC
		ENDM
		;16-BIT SEGMENT-RELATIVE
		DD	LOC2_8
		DD	LOC_9
		DD	LOC_10_PROT
		DD	LOC_11_PROT
		DD	LOC2_12
		DD	LOC_13_PROT
		REPT	2
		DD	BAD_MYLOC
		ENDM
		;32-BIT SEGMENT-RELATIVE
		DD	BAD_MYLOC
		DD	LOC_DWORD_OFFSET
		DD	LOC_DWORD_OFFSET	;TLS
		DD	LOC_FWORD_PTR_PROT
		DD	BAD_MYLOC
		DD	LOC_DWORD_OFFSET1_PROT
		DD	BAD_MYLOC
		DD	BAD_MYLOC

endif

if	fg_pe

		ALIGN	4

LOC_CALLTBL_PE	LABEL	DWORD
		;
		;16-BIT SELF-RELATIVE
		;
		DD	LOC_0_PE		;0
		DD	BAD_MYLOC		;16-BIT SELF-RELATIVE ILLEGAL
		REPT	6
		DD	BAD_MYLOC
		ENDM
		;32-BIT SELF-RELATIVE
		DD	BAD_MYLOC		;8
		DD	LOC_32SELF_PE
		REPT	6
		DD	BAD_MYLOC
		ENDM
		;16-BIT SEGMENT-RELATIVE
		DD	LOC2_8			;LO BYTE 	;16
		DD	LOC_9_PE		;16-BIT OFFSET, ???
		DD	BAD_MYLOC			;SEGMENT
		DD	BAD_MYLOC			;16:16
		DD	LOC2_12			;HI BYTE
		DD	LOC_9_PE		;16 BIT OFFSET
		REPT	2
		DD	BAD_MYLOC
		ENDM
		;32-BIT SEGMENT-RELATIVE	
		DD	BAD_MYLOC		;24
		DD	LOC_DWORD_OFFSET_PE
		DD	LOC_DWORD_OFFSET_TLS	;
		DD	BAD_MYLOC			;FWORD 16:32...
		DD	BAD_MYLOC
		DD	LOC_DWORD_OFFSET_PE
		DD	BAD_MYLOC
		DD	BAD_MYLOC

endif

if	fg_norm_exe

		ALIGN	4

LOC_CALLTBL_REAL	LABEL	DWORD
		;
		;16-BIT SELF-RELATIVE
		;
		DD	LOC_0_REAL
		DD	LOC_1_REAL
		REPT	6
		DD	BAD_MYLOC
		ENDM
		;32-BIT SELF-RELATIVE
		DD	BAD_MYLOC
		DD	LOC_32SELF_REAL
		REPT	6
		DD	BAD_MYLOC
		ENDM
		;16-BIT SEGMENT-RELATIVE
		DD	LOC2_8
		DD	LOC_9
		DD	LOC_10_REAL
		DD	LOC_11_REAL
		DD	LOC2_12
		DD	LOC_13_REAL
		REPT	2
		DD	BAD_MYLOC
		ENDM
		;32-BIT SEGMENT-RELATIVE
		DD	BAD_MYLOC
		DD	LOC_DWORD_OFFSET
		DD	LOC_DWORD_OFFSET	;TLS
		DD	LOC_FWORD_PTR_REAL
		DD	BAD_MYLOC
		DD	LOC_DWORD_OFFSET1_REAL
		DD	BAD_MYLOC
		DD	BAD_MYLOC

endif

if	fg_segm

		ALIGN	4

IMP_CALLTBL	LABEL	DWORD
		;
		;16-BIT SELF-RELATIVE		ALL ILLEGAL ON IMPORTS
		;
		REPT	8
		DD	BAD_MYLOC_IMP
		ENDM
		;
		;32-BIT SELF-RELATIVE		ALL ILLEGAL ON IMPORTS - TODAY
		;
		REPT	8
		DD	BAD_MYLOC_IMP
		ENDM
		;
		;16-BIT SEGMENT-RELATIVE
		;
		DD	IMP_8
		DD	IMP_9
		DD	IMP_10
		DD	IMP_11
		DD	BAD_MYLOC
		DD	IMP_9	;WIERD...
		REPT	2
		DD	BAD_MYLOC
		ENDM
		;
		;32-BIT SEGMENT-RELATIVE
		;
		DD	BAD_MYLOC
		DD	IMP_DWORD_OFFSET
		DD	IMP_DWORD_OFFSET	;tls is not an import...
		DD	IMP_FWORD_PTR
		DD	BAD_MYLOC
		DD	IMP_DWORD_OFFSET
		DD	BAD_MYLOC
		DD	BAD_MYLOC

endif

FIX2_EXT_TYPE_XLAT	LABEL	BYTE

		DB	0		;SYM_UNDEFINED
		DB	MASK SEG_ASEG	;SYM_ASEG
		DB	MASK SEG_RELOC	;SYM_RELOCATABLE
		DB	0		;SYM_NEAR_COMMUNAL
		DB	0		;SYM_FAR_COMMUNAL
		DB	0		;SYM_HUGE_COMMUNAL
		DB	MASK SEG_ASEG + MASK SEG_CONST	;SYM_CONST
		DB	0		;SYM_LIBRARY
		DB	0		;SYM_IMPORT
		DB	0		;SYM_PROMISED
		DB	0		;SYM_UNDEFINED
		DB	0		;WEAK_eXTRN
		DB	0		;POS_WEAK
		DB	0		;LIBRARY_LIST
		DB	0		;BVIRDEF
		DB	0		;ALIASED
		DB	0		;COMDAT
		DB	0		;WEAK-DEFINED
		DB	10 DUP(?)
		DB	0		;__imp__
		DB	0		;UNDECORATED

.ERRNZ	($-FIX2_EXT_TYPE_XLAT)-NSYM_SIZE/2

if	debug

START_MSG		DB	SIZEOF START_MSG-1,'Doing Start Address',0DH,0AH
FARCALL_MSG		DB	SIZEOF FARCALL_MSG-1,'Doing FARCALLTRANSLATION',0DH,0AH
FARCALLFINI_MSG		DB	SIZEOF FARCALLFINI_MSG-1,'Finished FARCALLTRANSLATION',0DH,0AH

endif

#endif
